Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15490490
D17749.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
8 KB
Referenced Files
None
Subscribers
None
D17749.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1724,6 +1724,7 @@
'PHUIListItemView' => 'view/phui/PHUIListItemView.php',
'PHUIListView' => 'view/phui/PHUIListView.php',
'PHUIListViewTestCase' => 'view/layout/__tests__/PHUIListViewTestCase.php',
+ 'PHUINextPrevView' => 'view/phui/PHUINextPrevView.php',
'PHUIObjectBoxView' => 'view/phui/PHUIObjectBoxView.php',
'PHUIObjectItemListExample' => 'applications/uiexample/examples/PHUIObjectItemListExample.php',
'PHUIObjectItemListView' => 'view/phui/PHUIObjectItemListView.php',
@@ -6730,6 +6731,7 @@
'PHUIListItemView' => 'AphrontTagView',
'PHUIListView' => 'AphrontTagView',
'PHUIListViewTestCase' => 'PhabricatorTestCase',
+ 'PHUINextPrevView' => 'AphrontView',
'PHUIObjectBoxView' => 'AphrontTagView',
'PHUIObjectItemListExample' => 'PhabricatorUIExample',
'PHUIObjectItemListView' => 'AphrontTagView',
diff --git a/src/applications/phriction/controller/PhrictionDocumentController.php b/src/applications/phriction/controller/PhrictionDocumentController.php
--- a/src/applications/phriction/controller/PhrictionDocumentController.php
+++ b/src/applications/phriction/controller/PhrictionDocumentController.php
@@ -220,6 +220,26 @@
}
$prop_list = phutil_tag_div('phui-document-view-pro-box', $prop_list);
+ $pager = new PHUINextPrevView();
+ if ($request->getInt('v') != null) {
+ $pager->setOffset($request->getInt('v'));
+ } else {
+ // In Phriction, v=0 points to the last version
+ // We must handle this and set offset manually
+ // to prevent the NEXT button from appearing
+ $content = id(new PhrictionContent())->load($document->getContentID());
+ $pager->setOffset($content->getVersion());
+ }
+ $pager->setURI($request->getRequestURI(), 'v');
+
+ $next_prev_version = id(new PhrictionContent())->loadAllWhere(
+ 'documentID = %d ORDER BY version LIMIT %d,%d',
+ $document->getID(),
+ max(0, $pager->getOffset() - 1),
+ $pager->getPageSize() + 1);
+
+ $next_prev_version = $pager->sliceResults($next_prev_version);
+
$page_content = id(new PHUIDocumentViewPro())
->setHeader($header)
->setToc($toc)
@@ -228,6 +248,7 @@
$version_note,
$move_notice,
$core_content,
+ $pager,
));
return $this->newPage()
diff --git a/src/view/phui/PHUINextPrevView.php b/src/view/phui/PHUINextPrevView.php
new file mode 100644
--- /dev/null
+++ b/src/view/phui/PHUINextPrevView.php
@@ -0,0 +1,212 @@
+<?php
+
+final class PHUINextPrevView extends AphrontView {
+
+ private $offset;
+ private $pageSize = 1;
+
+ private $count;
+ private $hasMorePages;
+
+ private $uri;
+ private $pagingParameter;
+ private $surroundingPages = 0;
+ private $enableKeyboardShortcuts;
+
+ public function setOffset($offset) {
+ $this->offset = max(0, $offset);
+ return $this;
+ }
+
+ public function getOffset() {
+ return $this->offset;
+ }
+
+ public function getPageSize() {
+ return $this->pageSize;
+ }
+
+ public function setCount($count) {
+ $this->count = $count;
+ return $this;
+ }
+
+ public function setHasMorePages($has_more) {
+ $this->hasMorePages = $has_more;
+ return $this;
+ }
+
+ public function setURI(PhutilURI $uri, $paging_parameter) {
+ $this->uri = $uri;
+ $this->pagingParameter = $paging_parameter;
+ return $this;
+ }
+
+ public function readFromRequest(AphrontRequest $request) {
+ $this->uri = $request->getRequestURI();
+ $this->pagingParameter = 'offset';
+ $this->offset = $request->getInt($this->pagingParameter);
+ return $this;
+ }
+
+ public function willShowPagingControls() {
+ return $this->hasMorePages || $this->getOffset();
+ }
+
+ public function getHasMorePages() {
+ return $this->hasMorePages;
+ }
+
+ private function computeCount() {
+ if ($this->count !== null) {
+ return $this->count;
+ }
+ return $this->getOffset()
+ + $this->getPageSize()
+ + ($this->hasMorePages ? 1 : 0);
+ }
+
+ private function isExactCountKnown() {
+ return $this->count !== null;
+ }
+
+ /**
+ * A common paging strategy is to select one extra record and use that to
+ * indicate that there's an additional page (this doesn't give you a
+ * complete page count but is often faster than counting the total number
+ * of items). This method will take a result array, slice it down to the
+ * page size if necessary, and call setHasMorePages() if there are more than
+ * one page of results.
+ *
+ * $results = queryfx_all(
+ * $conn,
+ * 'SELECT ... LIMIT %d, %d',
+ * $pager->getOffset(),
+ * $pager->getPageSize() + 1);
+ * $results = $pager->sliceResults($results);
+ *
+ * @param list Result array.
+ * @return list One page of results.
+ */
+ public function sliceResults(array $results) {
+ if (count($results) > $this->getPageSize()) {
+ $results = array_slice($results, 0, $this->getPageSize(), true);
+ $this->setHasMorePages(true);
+ }
+ return $results;
+ }
+
+ public function setEnableKeyboardShortcuts($enable) {
+ $this->enableKeyboardShortcuts = $enable;
+ return $this;
+ }
+
+ public function render() {
+ if (!$this->uri) {
+ throw new PhutilInvalidStateException('setURI');
+ }
+
+ require_celerity_resource('phui-pager-css');
+
+ $page = (int)floor($this->getOffset() / $this->getPageSize());
+ $last = ((int)ceil($this->computeCount() / $this->getPageSize())) - 1;
+ $near = $this->surroundingPages;
+
+ $min = $page - $near;
+ $max = $page + $near;
+
+ // Limit the window size to no larger than the number of available pages.
+ if ($max - $min > $last) {
+ $max = $min + $last;
+ if ($max == $min) {
+ return phutil_tag('div', array('class' => 'phui-pager-view'), '');
+ }
+ }
+
+ // Slide the window so it is entirely over displayable pages.
+ if ($min < 0) {
+ $max += 0 - $min;
+ $min += 0 - $min;
+ }
+
+ if ($max > $last) {
+ $min -= $max - $last;
+ $max -= $max - $last;
+ }
+
+
+ // Build up a list of <index, label, css-class> tuples which describe the
+ // links we'll display, then render them all at once.
+
+ $links = array();
+
+ $prev_index = null;
+ $next_index = null;
+
+ if ($page > 0) {
+ $links[] = array($page - 1, pht('Prev'), null);
+ $prev_index = $page - 1;
+ }
+
+ if ($page < $last && $last > 0) {
+ $links[] = array($page + 1, pht('Next'), null);
+ $next_index = $page + 1;
+ }
+
+ $base_uri = $this->uri;
+ $parameter = $this->pagingParameter;
+
+ if ($this->enableKeyboardShortcuts) {
+ $pager_links = array();
+ $pager_index = array(
+ 'prev' => $prev_index,
+ 'next' => $next_index,
+ );
+ foreach ($pager_index as $key => $index) {
+ if ($index !== null) {
+ $display_index = $this->getDisplayIndex($index);
+ $pager_links[$key] = (string)$base_uri->alter(
+ $parameter,
+ $display_index);
+ }
+ }
+ Javelin::initBehavior('phabricator-keyboard-pager', $pager_links);
+ }
+
+ // Convert tuples into rendered nodes.
+ $rendered_links = array();
+ foreach ($links as $link) {
+ list($index, $label, $class) = $link;
+ $display_index = $this->getDisplayIndex($index);
+ $link = $base_uri->alter($parameter, $display_index);
+ $rendered_links[] = id(new PHUIButtonView())
+ ->setTag('a')
+ ->setHref($link)
+ ->setColor(PHUIButtonView::GREY)
+ ->addClass('mml')
+ ->addClass($class)
+ ->setText($label);
+ }
+
+ return phutil_tag(
+ 'div',
+ array(
+ 'class' => 'phui-pager-view',
+ ),
+ $rendered_links);
+ }
+
+ private function getDisplayIndex($page_index) {
+ $page_size = $this->getPageSize();
+ // Use a 1-based sequence for display so that the number in the URI is
+ // the same as the page number you're on.
+ if ($page_index == 0) {
+ // No need for the first page to say page=1.
+ $display_index = null;
+ } else {
+ $display_index = $page_index * $page_size;
+ }
+ return $display_index;
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 12, 5:55 PM (3 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7580850
Default Alt Text
D17749.diff (8 KB)
Attached To
Mode
D17749: Fixes T4815
Attached
Detach File
Event Timeline
Log In to Comment