diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 45f7406a5a..d7542b179c 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -242,6 +242,7 @@ phutil_register_library_map(array( 'ConpherenceReplyHandler' => 'applications/conpherence/mail/ConpherenceReplyHandler.php', 'ConpherenceSettings' => 'applications/conpherence/constants/ConpherenceSettings.php', 'ConpherenceThread' => 'applications/conpherence/storage/ConpherenceThread.php', + 'ConpherenceThreadListView' => 'applications/conpherence/view/ConpherenceThreadListView.php', 'ConpherenceThreadQuery' => 'applications/conpherence/query/ConpherenceThreadQuery.php', 'ConpherenceTransaction' => 'applications/conpherence/storage/ConpherenceTransaction.php', 'ConpherenceTransactionComment' => 'applications/conpherence/storage/ConpherenceTransactionComment.php', @@ -1956,6 +1957,7 @@ phutil_register_library_map(array( 0 => 'ConpherenceDAO', 1 => 'PhabricatorPolicyInterface', ), + 'ConpherenceThreadListView' => 'AphrontView', 'ConpherenceThreadQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'ConpherenceTransaction' => 'PhabricatorApplicationTransaction', 'ConpherenceTransactionComment' => 'PhabricatorApplicationTransactionComment', diff --git a/src/applications/conpherence/controller/ConpherenceController.php b/src/applications/conpherence/controller/ConpherenceController.php index 2e0ed97eb3..34c2f11694 100644 --- a/src/applications/conpherence/controller/ConpherenceController.php +++ b/src/applications/conpherence/controller/ConpherenceController.php @@ -5,26 +5,6 @@ */ abstract class ConpherenceController extends PhabricatorController { private $conpherences; - private $readConpherences; - private $unreadConpherences; - - public function setUnreadConpherences(array $conpherences) { - assert_instances_of($conpherences, 'ConpherenceThread'); - $this->unreadConpherences = $conpherences; - return $this; - } - public function getUnreadConpherences() { - return $this->unreadConpherences; - } - - public function setReadConpherences(array $conpherences) { - assert_instances_of($conpherences, 'ConpherenceThread'); - $this->readConpherences = $conpherences; - return $this; - } - public function getReadConpherences() { - return $this->readConpherences; - } /** * Try for a full set of unread conpherences, and if we fail @@ -70,88 +50,22 @@ abstract class ConpherenceController extends PhabricatorController { $unread_conpherences = array_select_keys( $all_conpherences, array_keys($unread)); - $this->setUnreadConpherences($unread_conpherences); $read_conpherences = array_select_keys( $all_conpherences, array_keys($read)); - $this->setReadConpherences($read_conpherences); - return $this; - } - - public function buildSideNavView($filter = null, $for_application = false) { - require_celerity_resource('conpherence-menu-css'); - $unread_conpherences = $this->getUnreadConpherences(); - $read_conpherences = $this->getReadConpherences(); - - $user = $this->getRequest()->getUser(); - $menu = new PhabricatorMenuView(); - $nav = AphrontSideNavFilterView::newFromMenu($menu); - $nav->addClass('conpherence-menu'); - $nav->setMenuID('conpherence-menu'); - - if (!$for_application) { - $nav->addMenuItem( - id(new PhabricatorMenuItemView()) - ->setName(pht('New Conversation')) - ->setWorkflow(true) - ->setKey('new') - ->setHref($this->getApplicationURI('new/')) - ->setType(PhabricatorMenuItemView::TYPE_BUTTON)); - - $nav->addLabel(pht('Unread')); - $nav = $this->addConpherencesToNav( - $unread_conpherences, - $nav, - false); - $nav->addLabel(pht('Read')); - $nav = $this->addConpherencesToNav( - $read_conpherences, - $nav, - true); - $nav->selectFilter($filter); - } else { - $nav->addFilter( - 'new', - pht('New Conversation'), - $this->getApplicationURI('new/')); - - } - return $nav; - } - - private function addConpherencesToNav( - array $conpherences, - AphrontSideNavFilterView $nav, - $read = false) { - - $user = $this->getRequest()->getUser(); - foreach ($conpherences as $conpherence) { - $item = $this->buildConpherenceMenuItem($conpherence); - - $nav->addCustomBlock($item->render()); - } - if (empty($conpherences) || $read) { - $nav->addCustomBlock($this->getNoConpherencesBlock()); - } - - return $nav; - } - - private function getNoConpherencesBlock() { - return phutil_tag( - 'div', - array( - 'class' => 'no-conpherences-menu-item' - ), - pht('No more conpherences.')); + return array($unread_conpherences, $read_conpherences); } public function buildApplicationMenu() { - return $this->buildSideNavView( - $filter = null, - $for_application = true)->getMenu(); + $nav = new PhabricatorMenuView(); + + $nav->newLink( + pht('New Conversation'), + $this->getApplicationURI('new/')); + + return $nav; } public function buildApplicationCrumbs() { @@ -170,39 +84,6 @@ abstract class ConpherenceController extends PhabricatorController { return $crumbs; } - protected function buildConpherenceMenuItem($conpherence) { - - $user = $this->getRequest()->getUser(); - $uri = $this->getApplicationURI($conpherence->getID().'/'); - $data = $conpherence->getDisplayData( - $user, - null); - $title = $data['title']; - $subtitle = $data['subtitle']; - $unread_count = $data['unread_count']; - $epoch = $data['epoch']; - $image = $data['image']; - $snippet = $data['snippet']; - - $item = id(new ConpherenceMenuItemView()) - ->setUser($user) - ->setTitle($title) - ->setSubtitle($subtitle) - ->setHref($uri) - ->setEpoch($epoch) - ->setImageURI($image) - ->setMessageText($snippet) - ->setUnreadCount($unread_count) - ->setID($conpherence->getPHID().'-nav-item') - ->addSigil('conpherence-menu-click') - ->setMetadata( - array( - 'id' => $conpherence->getID(), - )); - - return $item; - } - protected function buildHeaderPaneContent(ConpherenceThread $conpherence) { $user = $this->getRequest()->getUser(); $display_data = $conpherence->getDisplayData( diff --git a/src/applications/conpherence/controller/ConpherenceListController.php b/src/applications/conpherence/controller/ConpherenceListController.php index b138b676e1..d60f6053e8 100644 --- a/src/applications/conpherence/controller/ConpherenceListController.php +++ b/src/applications/conpherence/controller/ConpherenceListController.php @@ -3,8 +3,8 @@ /** * @group conpherence */ -final class ConpherenceListController extends - ConpherenceController { +final class ConpherenceListController + extends ConpherenceController { private $conpherenceID; @@ -45,23 +45,25 @@ final class ConpherenceListController extends $current_selection_epoch = $participant->getDateTouched(); } - $this->loadStartingConpherences($current_selection_epoch); - $nav = $this->buildSideNavView(); + list($unread, $read) = $this->loadStartingConpherences( + $current_selection_epoch); + + $thread_view = id(new ConpherenceThreadListView()) + ->setUser($user) + ->setBaseURI($this->getApplicationURI()) + ->setUnreadThreads($unread) + ->setReadThreads($read); $main_pane = id(new ConpherenceLayoutView()) - ->setBaseURI($this->getApplicationURI()); + ->setBaseURI($this->getApplicationURI()) + ->setThreadView($thread_view); if ($conpherence) { $main_pane->setThread($conpherence); } - $nav->appendChild( - array( - $main_pane, - )); - return $this->buildApplicationPage( - $nav, + $main_pane, array( 'title' => $title, 'device' => true, diff --git a/src/applications/conpherence/view/ConpherenceLayoutView.php b/src/applications/conpherence/view/ConpherenceLayoutView.php index fdcc57a059..34f9aaa2e0 100644 --- a/src/applications/conpherence/view/ConpherenceLayoutView.php +++ b/src/applications/conpherence/view/ConpherenceLayoutView.php @@ -4,6 +4,11 @@ final class ConpherenceLayoutView extends AphrontView { private $thread; private $baseURI; + private $threadView; + + public function getThreadView() { + return $this->threadView; + } public function setBaseURI($base_uri) { $this->baseURI = $base_uri; @@ -15,6 +20,11 @@ final class ConpherenceLayoutView extends AphrontView { return $this; } + public function setThreadView(ConpherenceThreadListView $thead_view) { + $this->threadView = $thead_view; + return $this; + } + public function render() { Javelin::initBehavior('conpherence-menu', @@ -40,47 +50,67 @@ final class ConpherenceLayoutView extends AphrontView { return javelin_tag( 'div', array( - 'id' => 'conpherence-main-pane', - 'sigil' => 'conpherence-layout' + 'sigil' => 'conpherence-layout', + 'class' => 'conpherence-layout', ), array( javelin_tag( 'div', array( - 'class' => 'conpherence-header-pane', - 'id' => 'conpherence-header-pane', - 'sigil' => 'conpherence-header', - ), - ''), - phutil_tag( - 'div', - array( - 'class' => 'conpherence-widget-pane', - 'id' => 'conpherence-widget-pane' + 'class' => 'phabricator-nav-column-background', ), ''), javelin_tag( 'div', array( - 'class' => 'conpherence-message-pane', - 'id' => 'conpherence-message-pane' + 'class' => 'conpherence-menu-pane phabricator-side-menu', + 'sigil' => 'conpherence-menu-pane', + ), + nonempty($this->threadView, '')), + javelin_tag( + 'div', + array( + 'class' => 'conpherence-content-pane', ), array( javelin_tag( 'div', array( - 'class' => 'conpherence-messages', - 'id' => 'conpherence-messages', - 'sigil' => 'conpherence-messages', + 'class' => 'conpherence-header-pane', + 'id' => 'conpherence-header-pane', + 'sigil' => 'conpherence-header', ), ''), phutil_tag( 'div', array( - 'id' => 'conpherence-form' + 'class' => 'conpherence-widget-pane', + 'id' => 'conpherence-widget-pane' ), - '') - )) + ''), + javelin_tag( + 'div', + array( + 'class' => 'conpherence-message-pane', + 'id' => 'conpherence-message-pane' + ), + array( + javelin_tag( + 'div', + array( + 'class' => 'conpherence-messages', + 'id' => 'conpherence-messages', + 'sigil' => 'conpherence-messages', + ), + ''), + phutil_tag( + 'div', + array( + 'id' => 'conpherence-form' + ), + '') + )), + )), )); } diff --git a/src/applications/conpherence/view/ConpherenceThreadListView.php b/src/applications/conpherence/view/ConpherenceThreadListView.php new file mode 100644 index 0000000000..cf204c9d20 --- /dev/null +++ b/src/applications/conpherence/view/ConpherenceThreadListView.php @@ -0,0 +1,112 @@ +baseURI = $base_uri; + return $this; + } + + public function setUnreadThreads(array $unread_threads) { + assert_instances_of($unread_threads, 'ConpherenceThread'); + $this->unreadThreads = $unread_threads; + return $this; + } + + public function setReadThreads(array $read_threads) { + assert_instances_of($read_threads, 'ConpherenceThread'); + $this->readThreads = $read_threads; + return $this; + } + + public function render() { + require_celerity_resource('conpherence-menu-css'); + + $menu = id(new PhabricatorMenuView()) + ->addClass('conpherence-menu') + ->setID('conpherence-menu'); + + $menu->addMenuItem( + id(new PhabricatorMenuItemView()) + ->setName(pht('New Conversation')) + ->setWorkflow(true) + ->setKey('new') + ->setHref($this->baseURI.'new/') + ->setType(PhabricatorMenuItemView::TYPE_BUTTON)); + + $menu->newLabel(pht('Unread')); + $this->addThreadsToMenu($menu, $this->unreadThreads, $read = false); + $menu->newLabel(pht('Read')); + $this->addThreadsToMenu($menu, $this->readThreads, $read = true); + + return $menu; + } + + private function renderThread(ConpherenceThread $thread) { + $user = $this->getUser(); + + $uri = $this->baseURI.$thread->getID().'/'; + $data = $thread->getDisplayData($user, null); + $title = $data['title']; + $subtitle = $data['subtitle']; + $unread_count = $data['unread_count']; + $epoch = $data['epoch']; + $image = $data['image']; + $snippet = $data['snippet']; + + $item = id(new ConpherenceMenuItemView()) + ->setUser($user) + ->setTitle($title) + ->setSubtitle($subtitle) + ->setHref($uri) + ->setEpoch($epoch) + ->setImageURI($image) + ->setMessageText($snippet) + ->setUnreadCount($unread_count) + ->setID($thread->getPHID().'-nav-item') + ->addSigil('conpherence-menu-click') + ->setMetadata( + array( + 'id' => $thread->getID(), + )); + + return id(new PhabricatorMenuItemView()) + ->setType(PhabricatorMenuItemView::TYPE_CUSTOM) + ->setName($item); + } + + private function addThreadsToMenu( + PhabricatorMenuView $menu, + array $conpherences, + $read = false) { + + foreach ($conpherences as $conpherence) { + $item = $this->renderThread($conpherence); + $menu->addMenuItem($item); + } + + if (empty($conpherences) || $read) { + $menu->addMenuItem($this->getNoConpherencesBlock()); + } + + return $menu; + } + + private function getNoConpherencesBlock() { + $message = phutil_tag( + 'div', + array( + 'class' => 'no-conpherences-menu-item' + ), + pht('No more conpherences.')); + + return id(new PhabricatorMenuItemView()) + ->setType(PhabricatorMenuItemView::TYPE_CUSTOM) + ->setName($message); + } + +} diff --git a/webroot/rsrc/css/application/conpherence/header-pane.css b/webroot/rsrc/css/application/conpherence/header-pane.css index 9d42c4991a..611bf0b307 100644 --- a/webroot/rsrc/css/application/conpherence/header-pane.css +++ b/webroot/rsrc/css/application/conpherence/header-pane.css @@ -2,10 +2,6 @@ * @provides conpherence-header-pane-css */ -#conpherence-main-pane { - position: relative; -} - .conpherence-header-pane { border-bottom: 1px solid #ccc; height: 80px; diff --git a/webroot/rsrc/css/application/conpherence/menu.css b/webroot/rsrc/css/application/conpherence/menu.css index eed6dc4973..9340124e82 100644 --- a/webroot/rsrc/css/application/conpherence/menu.css +++ b/webroot/rsrc/css/application/conpherence/menu.css @@ -2,36 +2,31 @@ * @provides conpherence-menu-css */ -.no-conpherences-menu-item { - color: #a1a5a9; - border-top: solid 1px #3B3D3E; - padding: 20px 0; - margin: 0px auto; - width: 300px; - text-align: center; -} - -.conpherence-menu .phabricator-nav-column-background, -.conpherence-menu .phabricator-nav-local { - width: 300px; -} -.conpherence-menu .phabricator-nav-local { +.conpherence-layout { + position: fixed; + bottom: 0; + left: 0; + right: 0; top: 44px; - bottom: 0px; } -.conpherence-menu .phabricator-nav-drag { - left: 300px; -} - -.device-desktop .conpherence-menu .phabricator-nav-content { - margin-left: 300px !important; -} - -.conpherence-menu .phabricator-menu-view { +.conpherence-menu-pane { + width: 300px; + position: absolute; overflow-x: hidden; overflow-y: auto; - margin-bottom: 0; + top: 0; + bottom: 0; +} + +.conpherence-content-pane { + margin-left: 300px; + position: relative; +} + +div.conpherence-layout .phabricator-nav-column-background { + display: block; + width: 300px; } .conpherence-menu .conpherence-menu-item-view { @@ -122,3 +117,12 @@ color: white; font-size: 12px; } + +.no-conpherences-menu-item { + color: #a1a5a9; + border-top: solid 1px #3B3D3E; + padding: 20px 0; + margin: 0px auto; + width: 300px; + text-align: center; +} diff --git a/webroot/rsrc/css/core/z-index.css b/webroot/rsrc/css/core/z-index.css index acd6b3f8e8..4cb84d5476 100644 --- a/webroot/rsrc/css/core/z-index.css +++ b/webroot/rsrc/css/core/z-index.css @@ -30,6 +30,10 @@ z-index: 4; } +.conpherence-menu-pane { + z-index: 4; +} + .phabricator-nav-drag { z-index: 4; }