@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 - make widget selector be a fun JS-based menu

Summary: Ref T3155. Also re-adds the ability to update Conpherence titles by letting user click the title and fill out a little dialogue. Also fixes a bunch of random bugs and what have you. I tried to make the javascript less mysterious by trying to code what's actually happening more explicitly. Still a work in progress all over the place but a good stopping point for feedback.

Test Plan: played around with Conpherence. In particular, went to /conpherence/ and re-sized and went to /conpherence/X/ and re-sized. Also loaded up my no conpherneces user.

Reviewers: epriestley

Reviewed By: epriestley

CC: chad, aran, Korvin

Maniphest Tasks: T3155

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

+321 -317
+8 -6
src/__celerity_resource_map__.php
··· 918 918 ), 919 919 'conpherence-header-pane-css' => 920 920 array( 921 - 'uri' => '/res/762c199d/rsrc/css/application/conpherence/header-pane.css', 921 + 'uri' => '/res/6d7bfc7e/rsrc/css/application/conpherence/header-pane.css', 922 922 'type' => 'css', 923 923 'requires' => 924 924 array( ··· 927 927 ), 928 928 'conpherence-menu-css' => 929 929 array( 930 - 'uri' => '/res/9991071e/rsrc/css/application/conpherence/menu.css', 930 + 'uri' => '/res/c955650e/rsrc/css/application/conpherence/menu.css', 931 931 'type' => 'css', 932 932 'requires' => 933 933 array( ··· 936 936 ), 937 937 'conpherence-message-pane-css' => 938 938 array( 939 - 'uri' => '/res/9b319b64/rsrc/css/application/conpherence/message-pane.css', 939 + 'uri' => '/res/383af93e/rsrc/css/application/conpherence/message-pane.css', 940 940 'type' => 'css', 941 941 'requires' => 942 942 array( ··· 954 954 ), 955 955 'conpherence-widget-pane-css' => 956 956 array( 957 - 'uri' => '/res/c0131a8b/rsrc/css/application/conpherence/widget-pane.css', 957 + 'uri' => '/res/7aaa78c5/rsrc/css/application/conpherence/widget-pane.css', 958 958 'type' => 'css', 959 959 'requires' => 960 960 array( ··· 1303 1303 ), 1304 1304 'javelin-behavior-conpherence-menu' => 1305 1305 array( 1306 - 'uri' => '/res/2bffa665/rsrc/js/application/conpherence/behavior-menu.js', 1306 + 'uri' => '/res/a7f3be10/rsrc/js/application/conpherence/behavior-menu.js', 1307 1307 'type' => 'js', 1308 1308 'requires' => 1309 1309 array( ··· 1335 1335 ), 1336 1336 'javelin-behavior-conpherence-widget-pane' => 1337 1337 array( 1338 - 'uri' => '/res/d2063fd4/rsrc/js/application/conpherence/behavior-widget-pane.js', 1338 + 'uri' => '/res/bc139f8e/rsrc/js/application/conpherence/behavior-widget-pane.js', 1339 1339 'type' => 'js', 1340 1340 'requires' => 1341 1341 array( ··· 1346 1346 4 => 'javelin-util', 1347 1347 5 => 'phabricator-notification', 1348 1348 6 => 'javelin-behavior-device', 1349 + 7 => 'phabricator-dropdown-menu', 1350 + 8 => 'phabricator-menu-item', 1349 1351 ), 1350 1352 'disk' => '/rsrc/js/application/conpherence/behavior-widget-pane.js', 1351 1353 ),
+12 -2
src/applications/conpherence/controller/ConpherenceController.php
··· 25 25 ->setName(pht('New Message')) 26 26 ->setHref($this->getApplicationURI('new/')) 27 27 ->setIcon('create') 28 - ->setWorkflow(true)); 28 + ->setWorkflow(true)) 29 + ->addAction( 30 + id(new PhabricatorMenuItemView()) 31 + ->setName(pht('Thread')) 32 + ->setHref('#') 33 + ->setIcon('action-menu') 34 + ->setStyle('display: none;') 35 + ->addClass('device-widgets-selector') 36 + ->addSigil('device-widgets-selector')); 29 37 return $crumbs; 30 38 } 31 39 ··· 38 46 } 39 47 $crumbs->addCrumb( 40 48 id(new PhabricatorCrumbView()) 41 - ->setName($title)); 49 + ->setName($title) 50 + ->setHref($this->getApplicationURI('update/'.$conpherence->getID().'/')) 51 + ->setWorkflow(true)); 42 52 43 53 return $crumbs; 44 54 }
+2 -1
src/applications/conpherence/controller/ConpherenceUpdateController.php
··· 92 92 case ConpherenceUpdateActions::METADATA: 93 93 $xactions = array(); 94 94 $updated = false; 95 - // all other metadata updates are continue requests 95 + // all metadata updates are continue requests 96 96 if (!$request->isContinueRequest()) { 97 97 break; 98 98 } ··· 103 103 ->setTransactionType(ConpherenceTransactionType::TYPE_TITLE) 104 104 ->setNewValue($title); 105 105 $updated = true; 106 + $response_mode = 'redirect'; 106 107 } 107 108 if (!$updated) { 108 109 $errors[] = pht(
+5 -1
src/applications/conpherence/controller/ConpherenceViewController.php
··· 91 91 ->setReplyForm($form) 92 92 ->setRole('thread'); 93 93 94 + $title = $conpherence->getTitle(); 95 + if (!$title) { 96 + $title = pht('Conpherence'); 97 + } 94 98 return $this->buildApplicationPage( 95 99 $layout, 96 100 array( 97 - 'title' => $conpherence->getTitle(), 101 + 'title' => $title, 98 102 'device' => true, 99 103 )); 100 104 }
+7 -76
src/applications/conpherence/controller/ConpherenceWidgetController.php
··· 69 69 $widgets[] = phutil_tag( 70 70 'div', 71 71 array( 72 - 'class' => 'widgets-header' 72 + 'class' => 'widgets-header', 73 73 ), 74 - phutil_tag( 75 - 'div', 76 - array( 77 - 'class' => 'widgets-header-icon-holder' 78 - ), 79 - array( 80 - javelin_tag( 81 - 'a', 82 - array( 83 - 'sigil' => 'conpherence-change-widget', 84 - 'meta' => array( 85 - 'widget' => 'conpherence-menu-pane', 86 - ), 87 - 'id' => 'conpherence-menu-pane-toggle', 88 - 'class' => 'sprite-conpherence conpherence_list_off', 89 - ), 90 - ''), 91 - javelin_tag( 92 - 'a', 93 - array( 94 - 'sigil' => 'conpherence-change-widget', 95 - 'meta' => array( 96 - 'widget' => 'conpherence-message-pane', 97 - ), 98 - 'id' => 'conpherence-message-pane-toggle', 99 - 'class' => 'sprite-conpherence conpherence_conversation_off', 100 - ), 101 - ''), 102 - javelin_tag( 103 - 'a', 104 - array( 105 - 'sigil' => 'conpherence-change-widget', 106 - 'meta' => array( 107 - 'widget' => 'widgets-people', 108 - ), 109 - 'id' => 'widgets-people-toggle', 110 - 'class' => 111 - 'sprite-conpherence conpherence_people_on conpherence_people_off' 112 - ), 113 - ''), 114 - javelin_tag( 115 - 'a', 116 - array( 117 - 'sigil' => 'conpherence-change-widget', 118 - 'meta' => array( 119 - 'widget' => 'widgets-files', 120 - ), 121 - 'id' => 'widgets-files-toggle', 122 - 'class' => 123 - 'sprite-conpherence conpherence_files_off' 124 - ), 125 - ''), 126 - javelin_tag( 127 - 'a', 128 - array( 129 - 'sigil' => 'conpherence-change-widget', 130 - 'meta' => array( 131 - 'widget' => 'widgets-calendar', 132 - ), 133 - 'id' => 'widgets-calendar-toggle', 134 - 'class' => 'sprite-conpherence conpherence_calendar_off', 135 - ), 136 - ''), 137 - javelin_tag( 138 - 'a', 139 - array( 140 - 'sigil' => 'conpherence-change-widget', 141 - 'meta' => array( 142 - 'widget' => 'widgets-settings', 143 - ), 144 - 'id' => 'widgets-settings-toggle', 145 - 'class' => 'sprite-conpherence conpherence_settings_off', 146 - ), 147 - '') 148 - ))); 74 + id(new PhabricatorActionHeaderView()) 75 + ->setHeaderColor(PhabricatorActionHeaderView::HEADER_GREY) 76 + ->setHeaderTitle('') 77 + ->setHeaderHref('#') 78 + ->setDropdown(true) 79 + ->addHeaderSigil('widgets-selector')); 149 80 $user = $this->getRequest()->getUser(); 150 81 // now the widget bodies 151 82 $widgets[] = javelin_tag(
+3 -1
src/applications/conpherence/storage/ConpherenceThread.php
··· 157 157 $lucky_handle = reset($handles); 158 158 } 159 159 160 - $title = $this->getTitle(); 160 + $title = $js_title = $this->getTitle(); 161 161 if (!$title) { 162 162 $title = $lucky_handle->getName(); 163 + $js_title = pht('Conpherence'); 163 164 } 164 165 $img_src = $lucky_handle->getImageURI(); 165 166 ··· 191 192 192 193 return array( 193 194 'title' => $title, 195 + 'js_title' => $js_title, 194 196 'subtitle' => $subtitle, 195 197 'unread_count' => $unread_count, 196 198 'epoch' => $this->getDateModified(),
+9
src/applications/conpherence/view/ConpherenceFileWidgetView.php
··· 85 85 )); 86 86 } 87 87 88 + if (empty($files)) { 89 + $files_html[] = javelin_tag( 90 + 'div', 91 + array( 92 + 'class' => 'no-files', 93 + 'sigil' => 'no-files'), 94 + pht('No files.')); 95 + } 96 + 88 97 return phutil_tag( 89 98 'div', 90 99 array('class' => 'file-list'),
+23 -31
src/applications/conpherence/view/ConpherenceLayoutView.php
··· 65 65 'hasWidgets' => false, 66 66 )); 67 67 68 - $all_views = 1; 69 - $devices_only = 0; 70 68 Javelin::initBehavior( 71 69 'conpherence-widget-pane', 72 70 array( 73 - 'allViews' => $all_views, 74 - 'devicesOnly' => $devices_only, 75 - 'widgetRegistery' => array( 76 - 'conpherence-menu-pane' => $devices_only, 77 - 'conpherence-message-pane' => $devices_only, 78 - 'widgets-people' => $all_views, 79 - 'widgets-files' => $all_views, 80 - 'widgets-calendar' => $all_views, 81 - 'widgets-settings' => $all_views, 82 - ), 83 - 'widgetExtraNodes' => array( 84 - 'conpherence-menu-pane' => array( 85 - array( 86 - 'tagname' => 'div', 87 - 'sigil' => 'phabricator-nav-column-background', 88 - 'showstyle' => 'block', 89 - 'hidestyle' => 'none', 90 - 'desktopstyle' => 'block'), 91 - ) 92 - ), 93 - 'widgetToggleMap' => array( 94 - 'conpherence-menu-pane' => 'conpherence_list_on', 95 - 'conpherence-message-pane' => 'conpherence_conversation_on', 96 - 'widgets-people' => 'conpherence_people_on', 97 - 'widgets-files' => 'conpherence_files_on', 98 - 'widgets-calendar' => 'conpherence_calendar_on', 99 - 'widgets-settings' => 'conpherence_settings_on', 100 - ) 101 - )); 71 + 'selectChar' => "\xE2\x96\xBC", 72 + 'widgetRegistry' => array( 73 + 'conpherence-message-pane' => array( 74 + 'name' => pht('Thread'), 75 + 'deviceOnly' => true, 76 + ), 77 + 'widgets-people' => array( 78 + 'name' => pht('Participants'), 79 + 'deviceOnly' => false, 80 + ), 81 + 'widgets-files' => array( 82 + 'name' => pht('Files'), 83 + 'deviceOnly' => false, 84 + ), 85 + 'widgets-calendar' => array( 86 + 'name' => pht('Calendar'), 87 + 'deviceOnly' => false, 88 + ), 89 + 'widgets-settings' => array( 90 + 'name' => pht('Settings'), 91 + 'deviceOnly' => false, 92 + ), 93 + ))); 102 94 103 95 return javelin_tag( 104 96 'div',
+1 -1
src/applications/conpherence/view/ConpherenceThreadListView.php
··· 97 97 ->addSigil('conpherence-menu-click') 98 98 ->setMetadata( 99 99 array( 100 - 'title' => $title, 100 + 'title' => $data['js_title'], 101 101 'id' => $thread->getID(), 102 102 )); 103 103 }
+2 -2
src/view/AphrontTagView.php
··· 65 65 return $this; 66 66 } 67 67 68 - public function getClass() { 69 - return $this->class; 68 + public function getClasses() { 69 + return $this->classes; 70 70 } 71 71 72 72 public function setID($id) {
+19 -2
src/view/layout/PhabricatorActionHeaderView.php
··· 15 15 private $headerTitle; 16 16 private $headerHref; 17 17 private $headerIcon; 18 + private $headerSigils = array(); 18 19 private $actions = array(); 19 20 private $iconColor = PhabricatorActionHeaderView::ICON_GREY; 20 21 private $headerColor; 22 + private $dropdown; 23 + 24 + public function setDropdown($dropdown) { 25 + $this->dropdown = $dropdown; 26 + return $this; 27 + } 21 28 22 29 public function addAction(PHUIIconView $action) { 23 30 $this->actions[] = $action; ··· 39 46 return $this; 40 47 } 41 48 49 + public function addHeaderSigil($sigil) { 50 + $this->headerSigils[] = $sigil; 51 + return $this; 52 + } 53 + 42 54 public function setHeaderIcon($minicon) { 43 55 $this->headerIcon = $minicon; 44 56 return $this; ··· 64 76 if ($this->headerColor) { 65 77 $classes[] = 'sprite-gradient'; 66 78 $classes[] = 'gradient-'.$this->headerColor.'-header'; 79 + } 80 + 81 + if ($this->dropdown) { 82 + $classes[] = 'dropdown'; 67 83 } 68 84 69 85 $action_list = array(); ··· 89 105 90 106 $header_title = $this->headerTitle; 91 107 if ($this->headerHref) { 92 - $header_title = phutil_tag( 108 + $header_title = javelin_tag( 93 109 'a', 94 110 array( 95 111 'class' => 'phabricator-action-header-link', 96 - 'href' => $this->headerHref 112 + 'href' => $this->headerHref, 113 + 'sigil' => implode(' ', $this->headerSigils) 97 114 ), 98 115 $this->headerTitle); 99 116 }
+13 -8
src/view/layout/PhabricatorCrumbView.php
··· 6 6 private $href; 7 7 private $icon; 8 8 private $isLastCrumb; 9 + private $workflow; 10 + 11 + public function setWorkflow($workflow) { 12 + $this->workflow = $workflow; 13 + return $this; 14 + } 9 15 10 16 public function setName($name) { 11 17 $this->name = $name; ··· 71 77 $classes[] = 'phabricator-last-crumb'; 72 78 } 73 79 74 - return phutil_tag( 80 + return javelin_tag( 75 81 $this->href ? 'a' : 'span', 76 - array( 77 - 'href' => $this->href, 78 - 'class' => implode(' ', $classes), 79 - ), 80 - array($icon, $name, $divider)); 82 + array( 83 + 'sigil' => $this->workflow ? 'workflow' : null, 84 + 'href' => $this->href, 85 + 'class' => implode(' ', $classes), 86 + ), 87 + array($icon, $name, $divider)); 81 88 } 82 - 83 - 84 89 }
+9 -2
src/view/layout/PhabricatorCrumbsView.php
··· 50 50 $action->getName() 51 51 ); 52 52 53 + $action_sigils = $action->getSigils(); 54 + if ($action->getWorkflow()) { 55 + $action_sigils[] = 'workflow'; 56 + } 57 + $action_classes = $action->getClasses(); 58 + $action_classes[] = 'phabricator-crumbs-action'; 53 59 $actions[] = javelin_tag( 54 60 'a', 55 61 array( 56 62 'href' => $action->getHref(), 57 - 'class' => 'phabricator-crumbs-action', 58 - 'sigil' => $action->getWorkflow() ? 'workflow' : null, 63 + 'class' => implode(' ', $action_classes), 64 + 'sigil' => implode(' ', $action_sigils), 65 + 'style' => $action->getStyle() 59 66 ), 60 67 array( 61 68 $icon,
webroot/rsrc/css/application/conpherence/header-pane.cs

This is a binary file and will not be displayed.

-1
webroot/rsrc/css/application/conpherence/header-pane.css
··· 3 3 */ 4 4 5 5 .device .conpherence-header-pane { 6 - display: none; 7 6 }
+24 -19
webroot/rsrc/css/application/conpherence/menu.css
··· 22 22 } 23 23 24 24 .conpherence-menu-pane { 25 - width: 300px; 25 + width: 100%; 26 26 position: absolute; 27 27 overflow-x: hidden; 28 28 overflow-y: auto; 29 29 top: 0; 30 30 bottom: 0; 31 31 } 32 + .device-desktop .conpherence-layout .conpherence-menu-pane, 33 + .device-desktop .conpherence-layout .phabricator-nav-column-background { 34 + width: 280px; 35 + } 36 + .device .conpherence-menu-pane { 37 + top: 41px; 38 + } 39 + .device .conpherence-role-list .conpherence-menu-pane { 40 + top: 0px; 41 + } 32 42 33 43 .device-phone .conpherence-menu-pane { 34 44 -webkit-overflow-scrolling: touch; 35 - } 36 - 37 - .conpherence-content-pane { 38 - margin-left: 300px; 39 - position: relative; 40 45 } 41 46 42 47 .conpherence-layout .phabricator-nav-column-background { 43 48 display: block; 44 - width: 300px; 49 + width: 100%; 45 50 } 46 51 47 - .device .conpherence-menu-pane { 48 - top: 41px; 52 + .device .phabricator-nav-column-background { 53 + top: 44px; 49 54 } 50 55 51 - .device .phabricator-nav-column-background { 52 - top: 86px; 56 + .device .conpherence-role-thread .conpherence-menu-pane, 57 + .device .conpherence-role-thread .phabricator-nav-column-background { 58 + display: none; 53 59 } 54 60 55 - .device .conpherence-menu-pane, 56 - .device .phabricator-nav-column-background { 57 - display: none; 58 - width: 100%; 61 + .device-desktop .conpherence-content-pane { 62 + margin-left: 280px; 59 63 } 60 64 61 - .device .conpherence-content-pane { 62 - margin-left: 0; 65 + .conpherence-content-pane { 66 + margin-left: 0px; 67 + position: relative; 63 68 } 64 69 65 70 .conpherence-menu .conpherence-menu-item-view { ··· 106 111 color: #ffffff; 107 112 text-shadow: 0px 1px 1px #000000; 108 113 overflow: hidden; 109 - width: 160px; 114 + width: 140px; 110 115 text-overflow: ellipsis; 111 116 } 112 117 ··· 151 156 border-top: solid 1px #3B3D3E; 152 157 padding: 20px 0; 153 158 margin: 0px auto; 154 - width: 300px; 159 + width: 280px; 155 160 text-align: center; 156 161 }
+6 -8
webroot/rsrc/css/application/conpherence/message-pane.css
··· 4 4 5 5 .conpherence-message-pane { 6 6 position: fixed; 7 - left: 300px; 8 - right: 281px; 7 + left: 280px; 8 + right: 241px; 9 9 top: 76px; 10 10 min-width: 300px; 11 11 width: auto; ··· 15 15 .device .conpherence-message-pane { 16 16 left: 0; 17 17 right: 0; 18 - top: 85px; 19 18 width: 100%; 20 19 } 21 20 ··· 31 30 32 31 .conpherence-message-pane .conpherence-messages { 33 32 position: fixed; 34 - left: 300px; 35 - right: 281px; 33 + left: 280px; 34 + right: 241px; 36 35 top: 76px; 37 36 bottom: 190px; 38 37 overflow-y: auto; ··· 43 42 .device .conpherence-message-pane .conpherence-messages { 44 43 left: 0; 45 44 right: 0; 46 - top: 85px; 47 45 bottom: 3em; 48 46 width: 100%; 49 47 box-shadow: none; ··· 56 54 padding: 0; 57 55 position: fixed; 58 56 bottom: 0; 59 - left: 300px; 60 - right: 281px; 57 + left: 280px; 58 + right: 241px; 61 59 } 62 60 63 61 .device .conpherence-message-pane .remarkup-assist-bar {
+52 -57
webroot/rsrc/css/application/conpherence/widget-pane.css
··· 5 5 .conpherence-widget-pane { 6 6 position: fixed; 7 7 right: 0px; 8 - top: 76px; 9 - width: 280px; 8 + top: 74px; 9 + width: 240px; 10 10 height: 100%; 11 11 border-width: 0 0 0 1px; 12 12 border-color: #CCC; 13 13 border-style: solid; 14 - background: url('/rsrc/image/texture/dust_background.jpeg'); 15 14 overflow-y: auto; 16 15 -webkit-overflow-scrolling: touch; 17 16 } ··· 23 22 24 23 .conpherence-widget-pane .aphront-form-input { 25 24 margin: 0; 26 - width: 100%; 25 + width: 85%; 27 26 } 28 27 29 28 .conpherence-widget-pane .aphront-form-inset { 30 29 border: 0; 31 - background: url('/rsrc/image/texture/dust_background.jpeg'); 32 30 } 33 31 34 32 .conpherence-widget-pane .widgets-header { 35 - background-color: #d8dce2; 36 - box-shadow: 0px 2px 2px rgba(0,0,0,0.15); 33 + background: #F5F5F5; 34 + border-bottom: 1px solid #ccc; 37 35 } 38 36 39 - .conpherence-widget-pane .widgets-header .widgets-header-icon-holder { 40 - height: 40px; 41 - width: 280px; 42 - margin: 0px auto; 37 + .device .conpherence-widget-pane .widgets-header { 38 + display: none; 43 39 } 44 40 45 - .device-desktop .conpherence-widget-pane .widgets-header 46 - .widgets-header-icon-holder { 47 - width: 175px; 41 + .conpherence-widget-pane .widgets-header .caret { 42 + float: none; 43 + height: 0px; 44 + width: 0px; 45 + margin-right: 0px; 46 + border-top-color: #000; 48 47 } 49 - 50 - .conpherence-widget-pane .widgets-header .sprite-conpherence { 51 - display: block; 52 - width: 29px; 53 - height: 34px; 54 - margin: 4px 0px 0px 14px; 55 - float: left; 56 - clear: none; 48 + .conpherence-widget-pane .widgets-header a:hover { 49 + text-decoration: none; 57 50 } 58 - 59 - .conpherence-widget-pane .widgets-header .conpherence_list_on, 60 - .conpherence-widget-pane .widgets-header .conpherence_conversation_on, 61 - .conpherence-widget-pane .widgets-header .conpherence_people_on, 62 - .conpherence-widget-pane .widgets-header .conpherence_files_on, 63 - .conpherence-widget-pane .widgets-header .conpherence_calendar_on, 64 - .conpherence-widget-pane .widgets-header .conpherence_settings_on { 65 - border-bottom: 3px solid #525252; 51 + .device-desktop .conpherence-layout .device-widgets-selector { 52 + display: none; 66 53 } 67 54 68 - .device-desktop .conpherence-widget-pane .widgets-header 69 - #conpherence-menu-pane-toggle, 70 - .device-desktop .conpherence-widget-pane .widgets-header 71 - #conpherence-message-pane-toggle { 72 - display: none; 55 + .dropdown-menu-frame { 56 + width: 229px !important; 73 57 } 74 58 75 59 .conpherence-widget-pane .widgets-body { 76 60 position: fixed; 77 61 overflow-y: auto; 78 - top: 116px; 79 62 bottom: 0px; 80 63 width: 100%; 64 + top: 74px; 81 65 } 82 66 83 - .device .conpherence-widget-pane .widgets-body { 84 - top: 85px; 67 + .device-desktop .conpherence-widget-pane .widgets-body { 68 + top: 104px; 69 + width: 280px; 85 70 } 86 71 87 72 /* files widget */ 88 73 74 + .conpherence-widget-pane #widgets-files .no-files { 75 + width: 200px; 76 + padding: 20px; 77 + text-align: center; 78 + color: #555; 79 + } 89 80 .conpherence-widget-pane #widgets-files .file-entry { 90 81 padding: 12px 0px 14px 0px; 91 82 } ··· 103 94 top: -4px; 104 95 left: 20px; 105 96 overflow-x: hidden; 106 - width: 210px; 97 + width: 170px; 107 98 font-weight: bold; 108 99 } 109 100 .conpherence-widget-pane #widgets-files .file-uploaded-by { ··· 111 102 position: relative; 112 103 top: 0px; 113 104 left: 20px; 114 - width: 210px; 105 + width: 170px; 115 106 font-size: 11px; 116 107 } 117 108 118 109 .conpherence-widget-pane #widgets-files .file-extra { 119 110 display: block; 120 111 height: 120px; 121 - width: 160px; 112 + width: 120px; 122 113 margin: 8px 0px 8px 52px; 123 114 border: 1px solid #7289b7; 124 115 box-shadow: 0 0px 5px rgba(0,0,0,.25); ··· 128 119 .conpherence-widget-pane #widgets-files .divider { 129 120 float: left; 130 121 clear: both; 131 - width: 210px; 122 + width: 170px; 132 123 margin: 8px 0px 0px 50px; 133 124 border: 1px dashed #bfbfbf; 134 125 } ··· 146 137 147 138 .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view { 148 139 margin: 2px 0px 0px 0px; 149 - width: 280px; 140 + width: 240px; 150 141 } 151 142 .device .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view { 152 143 width: 100%; ··· 162 153 .aphront-multi-column-column-outer { 163 154 width: 20%; 164 155 margin-bottom: 0px; 156 + float: left; 157 + clear: none; 165 158 } 166 159 .conpherence-widget-pane #widgets-calendar .aphront-multi-column-view 167 160 .aphront-multi-column-column-last { ··· 219 212 border-top: 1px solid #bfbfbf; 220 213 border-bottom: 1px solid #bfbfbf; 221 214 padding: 5px 10px 5px 10px; 222 - width: 260px; 215 + width: 220px; 223 216 } 224 217 .device .conpherence-widget-pane #widgets-calendar .day-header { 225 218 width: 98%; ··· 237 230 .conpherence-widget-pane #widgets-calendar .divider { 238 231 float: left; 239 232 clear: both; 240 - width: 260px; 233 + width: 220px; 241 234 margin: 0px 0px 0px 10px; 242 235 border: 1px dashed #bfbfbf; 243 236 } ··· 256 249 float: left; 257 250 clear: both; 258 251 height: 60px; 259 - width: 280px; 252 + width: 240px; 260 253 } 261 254 .device .conpherence-widget-pane #widgets-calendar .user-status { 262 255 width: 100%; ··· 293 286 position: relative; 294 287 left: 40px; 295 288 top: 0px; 296 - width: 260px; 289 + width: 220px; 297 290 } 298 291 299 292 .conpherence-widget-pane #widgets-calendar .user-status .participant { ··· 302 295 top: 0px; 303 296 font-style: italic; 304 297 font-size: 11px; 305 - width: 260px; 298 + width: 220px; 306 299 } 307 300 308 301 .device .conpherence-widget-pane #widgets-calendar .user-status .description, ··· 323 316 /* people widget */ 324 317 .conpherence-widget-pane .people-widget-header { 325 318 float: left; 326 - width: 280px; 319 + width: 240px; 327 320 } 328 321 .conpherence-widget-pane .people-widget-header .divider { 329 322 float: left; 330 323 clear: both; 331 - width: 260px; 324 + width: 220px; 332 325 margin: 0px 0px 0px 10px; 333 326 border: 1px dashed #bfbfbf; 334 327 } ··· 339 332 .conpherence-widget-pane .people-widget-header .add-people-widget { 340 333 float: left; 341 334 padding: 10px 0px 10px 0px; 342 - width: 280px; 335 + width: 240px; 343 336 } 344 - 345 337 .device .conpherence-widget-pane .people-widget-header, 346 338 .device .conpherence-widget-pane .people-widget-header .add-people-widget { 347 339 width: 100%; 348 340 } 349 - 341 + .conpherence-widget-pane .add-people-widget .aphront-form-input { 342 + width: 100%; 343 + } 350 344 .conpherence-widget-pane .people-widget-header .add-people-widget 351 345 .aphront-form-control-tokenizer { 352 346 float: left; 353 - width: 180px; 347 + width: 142px; 354 348 padding: 0px 0px 0px 10px 355 349 } 356 350 .device .conpherence-widget-pane .people-widget-header .add-people-widget ··· 360 354 .conpherence-widget-pane .people-widget-header .add-people-widget 361 355 .people-add-button { 362 356 float: right; 363 - margin: 2px 10px 0px 0px; 357 + margin: 2px 8px 0px 0px; 364 358 padding: 3px 16px 4px 16px; 365 359 } 366 360 @-moz-document url-prefix() { ··· 371 365 } 372 366 .conpherence-widget-pane .person-entry { 373 367 float: left; 374 - width: 270px; 368 + width: 230px; 375 369 clear: both; 376 370 padding: 10px 0px 0px 8px; 377 371 } ··· 386 380 clear: none; 387 381 font-size: 14px; 388 382 font-weight: bold; 389 - width: 164px; 383 + width: 124px; 390 384 } 391 385 392 386 .conpherence-widget-pane .person-entry .pic { ··· 422 416 } 423 417 424 418 /* settings widget */ 419 + .conpherence-widget-pane .title-update, 425 420 .conpherence-widget-pane .notifications-update { 426 421 margin: 2px 0px 0px 8px; 427 422 }
+49 -31
webroot/rsrc/js/application/conpherence/behavior-menu.js
··· 97 97 var data = JX.Stratcom.getData(thread.node); 98 98 99 99 if (thread.visible !== null || !config.hasThread) { 100 - var uri = config.base_uri + data.id + '/'; 100 + var uri = config.base_uri + data.id + '/'; 101 101 new JX.Workflow(uri, {}) 102 102 .setHandler(onloadthreadresponse) 103 103 .start(); ··· 124 124 updatetoggledwidget(); 125 125 } 126 126 127 - function updatetoggledwidget() { 127 + function updatetoggledwidget(no_toggle) { 128 + JX.Stratcom.invoke( 129 + 'conpherence-toggle-widget', 130 + null, 131 + { 132 + widget : getdefaultwidget(), 133 + no_toggle : no_toggle 134 + }); 135 + } 136 + 137 + function getdefaultwidget() { 128 138 var device = JX.Device.getDevice(); 129 - if (device != 'desktop') { 130 - if (config.role == 'list') { 131 - JX.Stratcom.invoke( 132 - 'conpherence-toggle-widget', 133 - null, 134 - { 135 - widget : 'conpherence-menu-pane' 136 - } 137 - ); 138 - } else { 139 - JX.Stratcom.invoke( 140 - 'conpherence-toggle-widget', 141 - null, 142 - { 143 - widget : 'conpherence-message-pane' 144 - } 145 - ); 146 - } 147 - } else { 148 - JX.Stratcom.invoke( 149 - 'conpherence-toggle-widget', 150 - null, 151 - { 152 - widget : 'widgets-people' 153 - } 154 - ); 139 + var widget = 'conpherence-message-pane'; 140 + if (device == 'desktop') { 141 + widget = 'widgets-people'; 155 142 } 143 + return widget; 156 144 } 157 145 158 146 function onloadthreadresponse(response) { ··· 174 162 var root = JX.DOM.find(document, 'div', 'conpherence-layout'); 175 163 var messagesRoot = JX.DOM.find(root, 'div', 'conpherence-messages'); 176 164 messagesRoot.scrollTop = messagesRoot.scrollHeight; 165 + 166 + try { 167 + var device = JX.Device.getDevice(); 168 + var deviceWidgetSelector = JX.DOM.find( 169 + root, 170 + 'a', 171 + 'device-widgets-selector'); 172 + if (device != 'desktop') { 173 + JX.DOM.show(deviceWidgetSelector); 174 + updatetoggledwidget(true); 175 + } else { 176 + JX.DOM.hide(deviceWidgetSelector); 177 + } 178 + } catch (ex) { 179 + // not here yet 180 + } 177 181 } 178 182 179 183 JX.Stratcom.listen( ··· 262 266 if (new_device === old_device) { 263 267 return; 264 268 } 269 + 270 + if (old_device === null) { 271 + old_device = new_device; 272 + if (config.role == 'list') { 273 + if (new_device != 'desktop') { 274 + return; 275 + } 276 + } else { 277 + loadthreads(); 278 + return; 279 + } 280 + } 265 281 var update_toggled_widget = 266 282 new_device == 'desktop' || old_device == 'desktop'; 267 283 old_device = new_device; ··· 270 286 updatetoggledwidget(); 271 287 } 272 288 273 - if (!config.hasThreadList) { 274 - loadthreads(); 275 - } else { 289 + if (config.role == 'list') { 276 290 didloadthreads(); 291 + config.role = 'thread'; 292 + var root = JX.DOM.find(document, 'div', 'conpherence-layout'); 293 + JX.DOM.alterClass(root, 'conpherence-role-list', false); 294 + JX.DOM.alterClass(root, 'conpherence-role-thread', true); 277 295 } 278 296 } 279 297
+77 -68
webroot/rsrc/js/application/conpherence/behavior-widget-pane.js
··· 6 6 * javelin-util 7 7 * phabricator-notification 8 8 * javelin-behavior-device 9 + * phabricator-dropdown-menu 10 + * phabricator-menu-item 9 11 * @provides javelin-behavior-conpherence-widget-pane 10 12 */ 11 13 12 14 JX.behavior('conpherence-widget-pane', function(config) { 13 15 16 + var build_widget_selector = function (data) { 17 + var widgets = config.widgetRegistry; 18 + var root = JX.DOM.find(document, 'div', 'conpherence-layout'); 19 + var widgetPane = JX.DOM.find(root, 'div', 'conpherence-widget-pane'); 20 + var widgetHeader = JX.DOM.find(widgetPane, 'a', 'widgets-selector'); 21 + var mobileWidgetHeader = null; 22 + try { 23 + mobileWidgetHeader = JX.DOM.find( 24 + root, 25 + 'a', 26 + 'device-widgets-selector'); 27 + } catch (ex) { 28 + // is okay - no mobileWidgetHeader yet... 29 + } 30 + var widgetData = widgets[data.widget]; 31 + JX.DOM.setContent( 32 + widgetHeader, 33 + widgetData.name); 34 + JX.DOM.appendContent( 35 + widgetHeader, 36 + JX.$N('span', { className : 'caret' })); 37 + if (mobileWidgetHeader) { 38 + // this is fragile but adding a sigil to this element is awkward 39 + var mobileWidgetHeaderSpans = JX.DOM.scry(mobileWidgetHeader, 'span'); 40 + var mobileWidgetHeaderSpan = mobileWidgetHeaderSpans[1]; 41 + JX.DOM.setContent( 42 + mobileWidgetHeaderSpan, 43 + widgetData.name); 44 + } 45 + 46 + var menu = new JX.PhabricatorDropdownMenu(widgetHeader); 47 + menu.toggleAlignDropdownRight(false); 48 + var deviceMenu = null; 49 + if (mobileWidgetHeader) { 50 + deviceMenu = new JX.PhabricatorDropdownMenu(mobileWidgetHeader); 51 + } 52 + 53 + for (var widget in widgets) { 54 + widgetData = widgets[widget]; 55 + if (mobileWidgetHeader) { 56 + deviceMenu.addItem(new JX.PhabricatorMenuItem( 57 + widgetData.name, 58 + JX.bind(null, build_widget_selector, { widget : widget }), 59 + '#' 60 + ).setDisabled(widget == data.widget)); 61 + } 62 + if (widgetData.deviceOnly) { 63 + continue; 64 + } 65 + menu.addItem(new JX.PhabricatorMenuItem( 66 + widgetData.name, 67 + JX.bind(null, build_widget_selector, { widget : widget }), 68 + '#' 69 + ).setDisabled(widget == data.widget)); 70 + } 71 + if (data.no_toggle) { 72 + return; 73 + } 74 + toggle_widget(data); 75 + }; 76 + 14 77 var toggle_widget = function (data) { 78 + var widgets = config.widgetRegistry; 79 + var widgetData = widgets[data.widget]; 15 80 var device = JX.Device.getDevice(); 16 81 var is_desktop = device == 'desktop'; 17 - if (config.widgetRegistery[data.widget] == config.devicesOnly && 18 - is_desktop) { 82 + 83 + if (widgetData.deviceOnly && is_desktop) { 19 84 return; 20 85 } 21 86 22 - var root = JX.DOM.find(document, 'div', 'conpherence-layout'); 23 - var widgetPane = JX.DOM.find(root, 'div', 'conpherence-widget-pane'); 24 - var i; 25 - var tag_data; 26 - var node; 27 - 28 - for (var widget in config.widgetRegistery) { 29 - // device-only widgets are *always shown* on the desktop 30 - if (config.widgetRegistery[widget] == config.devicesOnly) { 31 - if (is_desktop) { 87 + for (var widget in config.widgetRegistry) { 88 + widgetData = widgets[widget]; 89 + if (widgetData.deviceOnly && is_desktop) { 90 + // some one off code for conpherence messages which are device-only 91 + // as a widget, but shown always on the desktop 92 + if (widget == 'conpherence-message-pane') { 32 93 JX.$(widget).style.display = 'block'; 33 - if (config.widgetExtraNodes[widget]) { 34 - for (i in config.widgetExtraNodes[widget]) { 35 - tag_data = config.widgetExtraNodes[widget][i]; 36 - node = JX.DOM.find(root, tag_data.tagname, tag_data.sigil); 37 - node.style.display = tag_data.desktopstyle; 38 - } 39 - } 40 - continue; 94 + JX.Stratcom.invoke('conpherence-redraw-thread', null, {}); 41 95 } 96 + continue; 42 97 } 43 - 44 - var cur_toggle = JX.$(widget + '-toggle'); 45 - var toggle_class = config.widgetToggleMap[widget]; 46 98 if (widget == data.widget) { 47 - JX.DOM.alterClass(cur_toggle, toggle_class, true); 48 99 JX.$(widget).style.display = 'block'; 49 - if (config.widgetRegistery[widget] == config.devicesOnly) { 50 - widgetPane.style.height = '42px'; 51 - } else { 52 - widgetPane.style.height = '100%'; 53 - } 54 - if (config.widgetExtraNodes[widget]) { 55 - for (i in config.widgetExtraNodes[widget]) { 56 - tag_data = config.widgetExtraNodes[widget][i]; 57 - node = JX.DOM.find(root, tag_data.tagname, tag_data.sigil); 58 - node.style.display = tag_data.showstyle; 59 - } 60 - } 61 - // some one off code for conpherence messages 100 + // some one off code for conpherence messages - fancier refresh tech 62 101 if (widget == 'conpherence-message-pane') { 63 102 JX.Stratcom.invoke('conpherence-redraw-thread', null, {}); 64 103 JX.Stratcom.invoke('conpherence-update-page-data', null, {}); 65 104 } 66 - // some one off code for conpherence list 67 - if (widget == 'conpherence-menu-pane') { 68 - JX.Stratcom.invoke( 69 - 'conpherence-update-page-data', 70 - null, 71 - { use_base_uri : true, title: 'Conpherence' } 72 - ); 73 - } 74 105 } else { 75 - JX.DOM.alterClass( 76 - cur_toggle, 77 - toggle_class, 78 - false 79 - ); 80 106 JX.$(widget).style.display = 'none'; 81 - if (config.widgetExtraNodes[widget]) { 82 - for (i in config.widgetExtraNodes[widget]) { 83 - tag_data = config.widgetExtraNodes[widget][i]; 84 - node = JX.DOM.find(root, tag_data.tagname, tag_data.sigil); 85 - node.style.display = tag_data.hidestyle; 86 - } 87 - } 88 107 } 89 108 } 90 109 }; 91 110 92 111 JX.Stratcom.listen( 93 - ['touchstart', 'mousedown'], 94 - 'conpherence-change-widget', 95 - function(e) { 96 - e.kill(); 97 - var data = e.getNodeData('conpherence-change-widget'); 98 - toggle_widget(data); 99 - } 100 - ); 101 - 102 - JX.Stratcom.listen( 103 112 'conpherence-toggle-widget', 104 113 null, 105 114 function (e) { 106 - toggle_widget(e.getData()); 115 + build_widget_selector(e.getData()); 107 116 } 108 117 ); 109 118