@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.

Make TabGroups a standalone UI element

Summary:
Ref T10628. Currently, tabs are part of ObjectBoxes. However, the code is a bit of a mess and I want to use them in some other contexts, notably the "prose diff" dialog to show "old raw, new raw, diff".

Pull them out, and update Files to use the new stuff. My plan is:

- Update all callsites to this stuff.
- Remove the builtin-in ObjectBox integration to simplify ObjectBox a bit.
- Move forward with T10628.

This is pretty straightforward. A couple of the sigils are a little weird, but I'll update the JS later. For now, the same JS can drive both old and new tabs.

Test Plan: Viewed files, everything was unchanged.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10628

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

+202 -7
+4
src/__phutil_library_map__.php
··· 1663 1663 'PHUISpacesNamespaceContextView' => 'applications/spaces/view/PHUISpacesNamespaceContextView.php', 1664 1664 'PHUIStatusItemView' => 'view/phui/PHUIStatusItemView.php', 1665 1665 'PHUIStatusListView' => 'view/phui/PHUIStatusListView.php', 1666 + 'PHUITabGroupView' => 'view/phui/PHUITabGroupView.php', 1667 + 'PHUITabView' => 'view/phui/PHUITabView.php', 1666 1668 'PHUITagExample' => 'applications/uiexample/examples/PHUITagExample.php', 1667 1669 'PHUITagView' => 'view/phui/PHUITagView.php', 1668 1670 'PHUITimelineEventView' => 'view/phui/PHUITimelineEventView.php', ··· 6194 6196 'PHUISpacesNamespaceContextView' => 'AphrontView', 6195 6197 'PHUIStatusItemView' => 'AphrontTagView', 6196 6198 'PHUIStatusListView' => 'AphrontTagView', 6199 + 'PHUITabGroupView' => 'AphrontTagView', 6200 + 'PHUITabView' => 'AphrontTagView', 6197 6201 'PHUITagExample' => 'PhabricatorUIExample', 6198 6202 'PHUITagView' => 'AphrontTagView', 6199 6203 'PHUITimelineEventView' => 'AphrontView',
+33 -6
src/applications/files/controller/PhabricatorFileInfoController.php
··· 182 182 $request = $this->getRequest(); 183 183 $viewer = $request->getUser(); 184 184 185 + $tab_group = id(new PHUITabGroupView()); 186 + $box->addTabGroup($tab_group); 187 + 185 188 $properties = id(new PHUIPropertyListView()); 186 - $box->addPropertyList($properties, pht('Details')); 189 + 190 + $tab_group->addTab( 191 + id(new PHUITabView()) 192 + ->setName(pht('Details')) 193 + ->setKey('details') 194 + ->appendChild($properties)); 187 195 188 196 if ($file->getAuthorPHID()) { 189 197 $properties->addProperty( ··· 195 203 pht('Created'), 196 204 phabricator_datetime($file->getDateCreated(), $viewer)); 197 205 198 - 199 206 $finfo = id(new PHUIPropertyListView()); 200 - $box->addPropertyList($finfo, pht('File Info')); 207 + 208 + $tab_group->addTab( 209 + id(new PHUITabView()) 210 + ->setName(pht('File Info')) 211 + ->setKey('info') 212 + ->appendChild($finfo)); 201 213 202 214 $finfo->addProperty( 203 215 pht('Size'), ··· 262 274 } 263 275 264 276 $storage_properties = new PHUIPropertyListView(); 265 - $box->addPropertyList($storage_properties, pht('Storage')); 277 + 278 + $tab_group->addTab( 279 + id(new PHUITabView()) 280 + ->setName(pht('Storage')) 281 + ->setKey('storage') 282 + ->appendChild($storage_properties)); 266 283 267 284 $storage_properties->addProperty( 268 285 pht('Engine'), ··· 285 302 $phids = $file->getObjectPHIDs(); 286 303 if ($phids) { 287 304 $attached = new PHUIPropertyListView(); 288 - $box->addPropertyList($attached, pht('Attached')); 305 + 306 + $tab_group->addTab( 307 + id(new PHUITabView()) 308 + ->setName(pht('Attached')) 309 + ->setKey('attached') 310 + ->appendChild($attached)); 289 311 290 312 $attached->addProperty( 291 313 pht('Attached To'), ··· 357 379 if ($engine) { 358 380 if ($engine->isChunkEngine()) { 359 381 $chunkinfo = new PHUIPropertyListView(); 360 - $box->addPropertyList($chunkinfo, pht('Chunks')); 382 + 383 + $tab_group->addTab( 384 + id(new PHUITabView()) 385 + ->setName(pht('Chunks')) 386 + ->setKey('chunks') 387 + ->appendChild($chunkinfo)); 361 388 362 389 $chunks = id(new PhabricatorFileChunkQuery()) 363 390 ->setViewer($viewer)
+8 -1
src/view/phui/PHUIObjectBoxView.php
··· 5 5 private $headerText; 6 6 private $color; 7 7 private $background; 8 + private $tabGroups = array(); 8 9 private $formErrors = null; 9 10 private $formSaved = false; 10 11 private $infoView; ··· 128 129 return $this; 129 130 } 130 131 132 + public function addTabGroup(PHUITabGroupView $view) { 133 + $this->tabGroups[] = $view; 134 + return $this; 135 + } 136 + 131 137 public function setInfoView(PHUIInfoView $view) { 132 138 $this->infoView = $view; 133 139 return $this; ··· 211 217 $i = 0; 212 218 foreach ($list as $item) { 213 219 $group->addPropertyList($item); 214 - if ($i > 0) { 220 + if ($i > 0 || $this->tabGroups) { 215 221 $item->addClass('phui-property-list-section-noninitial'); 216 222 } 217 223 $i++; ··· 405 411 $this->formSaved, 406 412 $exception_errors, 407 413 $this->form, 414 + $this->tabGroups, 408 415 $tabs, 409 416 $this->tabLists, 410 417 $showhide,
+83
src/view/phui/PHUITabGroupView.php
··· 1 + <?php 2 + 3 + final class PHUITabGroupView extends AphrontTagView { 4 + 5 + private $tabs = array(); 6 + 7 + protected function canAppendChild() { 8 + return false; 9 + } 10 + 11 + public function addTab(PHUITabView $tab) { 12 + $key = $tab->getKey(); 13 + $tab->lockKey(); 14 + 15 + if (isset($this->tabs[$key])) { 16 + throw new Exception( 17 + pht( 18 + 'Each tab in a tab group must have a unique key; attempting to add '. 19 + 'a second tab with a duplicate key ("%s").', 20 + $key)); 21 + } 22 + 23 + $this->tabs[$key] = $tab; 24 + 25 + return $this; 26 + } 27 + 28 + public function getSelectedTab() { 29 + if (!$this->tabs) { 30 + return null; 31 + } 32 + 33 + return head($this->tabs)->getKey(); 34 + } 35 + 36 + protected function getTagAttributes() { 37 + $tab_map = mpull($this->tabs, 'getContentID', 'getKey'); 38 + 39 + return array( 40 + 'sigil' => 'phui-object-box', 41 + 'meta' => array( 42 + 'tabMap' => $tab_map, 43 + ), 44 + ); 45 + } 46 + 47 + protected function getTagContent() { 48 + Javelin::initBehavior('phui-object-box-tabs'); 49 + 50 + $tabs = id(new PHUIListView()) 51 + ->setType(PHUIListView::NAVBAR_LIST); 52 + $content = array(); 53 + 54 + $selected_tab = $this->getSelectedTab(); 55 + foreach ($this->tabs as $tab) { 56 + $item = $tab->newMenuItem(); 57 + $tab_key = $tab->getKey(); 58 + 59 + if ($tab_key == $selected_tab) { 60 + $item->setSelected(true); 61 + $style = null; 62 + } else { 63 + $style = 'display: none;'; 64 + } 65 + 66 + $tabs->addMenuItem($item); 67 + 68 + $content[] = javelin_tag( 69 + 'div', 70 + array( 71 + 'style' => $style, 72 + 'id' => $tab->getContentID(), 73 + ), 74 + $tab); 75 + } 76 + 77 + return array( 78 + $tabs, 79 + $content, 80 + ); 81 + } 82 + 83 + }
+74
src/view/phui/PHUITabView.php
··· 1 + <?php 2 + 3 + final class PHUITabView extends AphrontTagView { 4 + 5 + private $name; 6 + private $key; 7 + private $keyLocked; 8 + private $contentID; 9 + 10 + public function setKey($key) { 11 + if ($this->keyLocked) { 12 + throw new Exception( 13 + pht( 14 + 'Attempting to change the key of a tab with a locked key ("%s").', 15 + $this->key)); 16 + } 17 + 18 + $this->key = $key; 19 + return $this; 20 + } 21 + 22 + public function hasKey() { 23 + return ($this->key !== null); 24 + } 25 + 26 + public function getKey() { 27 + if (!$this->hasKey()) { 28 + throw new PhutilInvalidStateException('setKey'); 29 + } 30 + 31 + return $this->key; 32 + } 33 + 34 + public function lockKey() { 35 + if (!$this->hasKey()) { 36 + throw new PhutilInvalidStateException('setKey'); 37 + } 38 + 39 + $this->keyLocked = true; 40 + 41 + return $this; 42 + } 43 + 44 + public function setName($name) { 45 + $this->name = $name; 46 + return $this; 47 + } 48 + 49 + public function getName() { 50 + return $this->name; 51 + } 52 + 53 + public function getContentID() { 54 + if ($this->contentID === null) { 55 + $this->contentID = celerity_generate_unique_node_id(); 56 + } 57 + 58 + return $this->contentID; 59 + } 60 + 61 + public function newMenuItem() { 62 + return id(new PHUIListItemView()) 63 + ->setName($this->getName()) 64 + ->setKey($this->getKey()) 65 + ->setType(PHUIListItemView::TYPE_LINK) 66 + ->setHref('#') 67 + ->addSigil('phui-object-box-tab') 68 + ->setMetadata( 69 + array( 70 + 'tabKey' => $this->getKey(), 71 + )); 72 + } 73 + 74 + }