@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 "renderer", "engine", and "encoding" sticky across reloads in Differential and Diffusion

Summary:
Ref T13455. Update the other "view state" properties to work like "highlight" now works.

Some complexity here arises from these concerns:

- In "View Standalone", we render the changeset inline. This is useful for debugging/development, and desirable to retain.
- In all other cases, we render the changeset with AJAX.

So the client needs to be able to learn about the "state" properties of the changeset on two different flows. Prior to this change, each pathway had a fair amount of unique code.

Then, some bookkeeping issues:

- At inital rendering time, we may not know which renderer will be selected: it may be based on the client viewport dimensions.
- Prior to this change, the client didn't separate "value of the property for the changeset as rendered" and "desired value of the property".

Test Plan:
- Viewed changes in Differential, Diffusion, and in standalone mode.
- Toggled renderer, character sets, and document engine (this one isn't terribly useful). Reloaded, saw them stick.
- Started typing a comment, cancelled it, hit the undo UI.

Maniphest Tasks: T13455

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

+264 -200
+25 -25
resources/celerity/map.php
··· 12 12 'core.pkg.css' => '86f155f9', 13 13 'core.pkg.js' => '705aec2c', 14 14 'differential.pkg.css' => '607c84be', 15 - 'differential.pkg.js' => 'd73a942b', 15 + 'differential.pkg.js' => '99e2cb01', 16 16 'diffusion.pkg.css' => '42c75c37', 17 17 'diffusion.pkg.js' => 'a98c0bf7', 18 18 'maniphest.pkg.css' => '35995d6d', ··· 377 377 'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => 'a2ab19be', 378 378 'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '1e413dc9', 379 379 'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8', 380 - 'rsrc/js/application/diff/DiffChangeset.js' => '7ccc4153', 381 - 'rsrc/js/application/diff/DiffChangesetList.js' => '2e636e0a', 382 - 'rsrc/js/application/diff/DiffInline.js' => 'a4a14a94', 380 + 'rsrc/js/application/diff/DiffChangeset.js' => '5a4e4a3b', 381 + 'rsrc/js/application/diff/DiffChangesetList.js' => '4769cfe7', 382 + 'rsrc/js/application/diff/DiffInline.js' => '16e97ebc', 383 383 'rsrc/js/application/diff/behavior-preview-link.js' => 'f51e9c17', 384 384 'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd', 385 385 'rsrc/js/application/differential/behavior-populate.js' => 'dfa1d313', ··· 774 774 'phabricator-darklog' => '3b869402', 775 775 'phabricator-darkmessage' => '26cd4b73', 776 776 'phabricator-dashboard-css' => '5a205b9d', 777 - 'phabricator-diff-changeset' => '7ccc4153', 778 - 'phabricator-diff-changeset-list' => '2e636e0a', 779 - 'phabricator-diff-inline' => 'a4a14a94', 777 + 'phabricator-diff-changeset' => '5a4e4a3b', 778 + 'phabricator-diff-changeset-list' => '4769cfe7', 779 + 'phabricator-diff-inline' => '16e97ebc', 780 780 'phabricator-drag-and-drop-file-upload' => '4370900d', 781 781 'phabricator-draggable-list' => '0169e425', 782 782 'phabricator-fatal-config-template-css' => '20babf50', ··· 1029 1029 'javelin-stratcom', 1030 1030 'javelin-util', 1031 1031 ), 1032 + '16e97ebc' => array( 1033 + 'javelin-dom', 1034 + ), 1032 1035 '1b6acc2a' => array( 1033 1036 'javelin-magical-init', 1034 1037 'javelin-util', ··· 1169 1172 'javelin-util', 1170 1173 'javelin-stratcom', 1171 1174 ), 1172 - '2e636e0a' => array( 1173 - 'javelin-install', 1174 - 'phuix-button-view', 1175 - ), 1176 1175 '2f1db1ed' => array( 1177 1176 'javelin-util', 1178 1177 ), ··· 1307 1306 'javelin-router', 1308 1307 'javelin-util', 1309 1308 'phabricator-busy', 1309 + ), 1310 + '4769cfe7' => array( 1311 + 'javelin-install', 1312 + 'phuix-button-view', 1310 1313 ), 1311 1314 '47a0728b' => array( 1312 1315 'javelin-behavior', ··· 1441 1444 'javelin-util', 1442 1445 'javelin-magical-init', 1443 1446 ), 1447 + '5a4e4a3b' => array( 1448 + 'javelin-dom', 1449 + 'javelin-util', 1450 + 'javelin-stratcom', 1451 + 'javelin-install', 1452 + 'javelin-workflow', 1453 + 'javelin-router', 1454 + 'javelin-behavior-device', 1455 + 'javelin-vector', 1456 + 'phabricator-diff-inline', 1457 + ), 1444 1458 '5a6f6a06' => array( 1445 1459 'javelin-behavior', 1446 1460 'javelin-quicksand', ··· 1611 1625 '7c4d8998' => array( 1612 1626 'javelin-install', 1613 1627 'javelin-dom', 1614 - ), 1615 - '7ccc4153' => array( 1616 - 'javelin-dom', 1617 - 'javelin-util', 1618 - 'javelin-stratcom', 1619 - 'javelin-install', 1620 - 'javelin-workflow', 1621 - 'javelin-router', 1622 - 'javelin-behavior-device', 1623 - 'javelin-vector', 1624 - 'phabricator-diff-inline', 1625 1628 ), 1626 1629 '80bff3af' => array( 1627 1630 'javelin-install', ··· 1827 1830 'javelin-dom', 1828 1831 'javelin-stratcom', 1829 1832 'javelin-vector', 1830 - ), 1831 - 'a4a14a94' => array( 1832 - 'javelin-dom', 1833 1833 ), 1834 1834 'a4aa75c4' => array( 1835 1835 'phui-button-css',
+4 -7
src/applications/differential/controller/DifferentialChangesetViewController.php
··· 205 205 ->setRightSideCommentMapping($right_source, $right_new) 206 206 ->setLeftSideCommentMapping($left_source, $left_new); 207 207 208 - $parser->readParametersFromRequest($request); 209 - 210 208 if ($left && $right) { 211 209 $parser->setOriginals($left, $right); 212 210 } ··· 274 272 if ($request->isAjax()) { 275 273 // NOTE: We must render the changeset before we render coverage 276 274 // information, since it builds some caches. 277 - $rendered_changeset = $parser->renderChangeset(); 275 + $response = $parser->newChangesetResponse(); 278 276 279 277 $mcov = $parser->renderModifiedCoverage(); 280 278 ··· 282 280 'differential-mcoverage-'.md5($changeset->getFilename()) => $mcov, 283 281 ); 284 282 285 - return id(new PhabricatorChangesetResponse()) 286 - ->setRenderedChangeset($rendered_changeset) 287 - ->setCoverage($coverage_data) 288 - ->setUndoTemplates($parser->getRenderer()->renderUndoTemplates()); 283 + $response->setCoverage($coverage_data); 284 + 285 + return $response; 289 286 } 290 287 291 288 $detail = id(new DifferentialChangesetListView())
+62 -55
src/applications/differential/parser/DifferentialChangesetParser.php
··· 44 44 private $highlightErrors; 45 45 private $disableCache; 46 46 private $renderer; 47 - private $characterEncoding; 48 47 private $highlightingDisabled; 49 48 private $showEditAndReplyLinks = true; 50 49 private $canMarkDone; ··· 58 57 59 58 private $highlightEngine; 60 59 private $viewer; 61 - private $documentEngineKey; 62 60 63 61 private $viewState; 64 62 ··· 95 93 return $this->viewState; 96 94 } 97 95 98 - public function setCharacterEncoding($character_encoding) { 99 - $this->characterEncoding = $character_encoding; 100 - return $this; 101 - } 102 - 103 - public function getCharacterEncoding() { 104 - return $this->characterEncoding; 105 - } 106 - 107 96 public function setRenderer(DifferentialChangesetRenderer $renderer) { 108 97 $this->renderer = $renderer; 109 98 return $this; 110 99 } 111 100 112 101 public function getRenderer() { 113 - if (!$this->renderer) { 114 - return new DifferentialChangesetTwoUpRenderer(); 115 - } 116 102 return $this->renderer; 117 103 } 118 104 ··· 161 147 return $this->viewer; 162 148 } 163 149 164 - public function setDocumentEngineKey($document_engine_key) { 165 - $this->documentEngineKey = $document_engine_key; 166 - return $this; 167 - } 150 + private function newRenderer() { 151 + $viewer = $this->getViewer(); 152 + $viewstate = $this->getViewstate(); 168 153 169 - public function getDocumentEngineKey() { 170 - return $this->documentEngineKey; 171 - } 154 + $renderer_key = $viewstate->getRendererKey(); 172 155 173 - public static function getDefaultRendererForViewer(PhabricatorUser $viewer) { 174 - $is_unified = $viewer->compareUserSetting( 175 - PhabricatorUnifiedDiffsSetting::SETTINGKEY, 176 - PhabricatorUnifiedDiffsSetting::VALUE_ALWAYS_UNIFIED); 156 + if ($renderer_key === null) { 157 + $is_unified = $viewer->compareUserSetting( 158 + PhabricatorUnifiedDiffsSetting::SETTINGKEY, 159 + PhabricatorUnifiedDiffsSetting::VALUE_ALWAYS_UNIFIED); 177 160 178 - if ($is_unified) { 179 - return '1up'; 161 + if ($is_unified) { 162 + $renderer_key = '1up'; 163 + } else { 164 + $renderer_key = $viewstate->getDefaultDeviceRendererKey(); 165 + } 180 166 } 181 167 182 - return null; 183 - } 184 - 185 - public function readParametersFromRequest(AphrontRequest $request) { 186 - $this->setCharacterEncoding($request->getStr('encoding')); 187 - $this->setDocumentEngineKey($request->getStr('engine')); 188 - 189 - $renderer = null; 190 - 191 - // If the viewer prefers unified diffs, always set the renderer to unified. 192 - // Otherwise, we leave it unspecified and the client will choose a 193 - // renderer based on the screen size. 194 - 195 - if ($request->getStr('renderer')) { 196 - $renderer = $request->getStr('renderer'); 197 - } else { 198 - $renderer = self::getDefaultRendererForViewer($request->getViewer()); 199 - } 200 - 201 - switch ($renderer) { 168 + switch ($renderer_key) { 202 169 case '1up': 203 - $this->setRenderer(new DifferentialChangesetOneUpRenderer()); 170 + $renderer = new DifferentialChangesetOneUpRenderer(); 204 171 break; 205 172 default: 206 - $this->setRenderer(new DifferentialChangesetTwoUpRenderer()); 173 + $renderer = new DifferentialChangesetTwoUpRenderer(); 207 174 break; 208 175 } 209 176 210 - return $this; 177 + return $renderer; 211 178 } 212 179 213 180 const CACHE_VERSION = 14; ··· 633 600 $skip_cache = true; 634 601 } 635 602 636 - if ($this->characterEncoding) { 603 + $character_encoding = $viewstate->getCharacterEncoding(); 604 + if ($character_encoding !== null) { 637 605 $skip_cache = true; 638 606 } 639 607 ··· 782 750 $range_len = null, 783 751 $mask_force = array()) { 784 752 753 + $renderer = $this->getRenderer(); 754 + if (!$renderer) { 755 + $renderer = $this->newRenderer(); 756 + $this->setRenderer($renderer); 757 + } 758 + 785 759 // "Top level" renders are initial requests for the whole file, versus 786 760 // requests for a specific range generated by clicking "show more". We 787 761 // generate property changes and "shield" UI elements only for toplevel 788 762 // requests. 789 763 $this->isTopLevel = (($range_start === null) && ($range_len === null)); 790 764 $this->highlightEngine = PhabricatorSyntaxHighlighter::newEngine(); 765 + 766 + $viewstate = $this->getViewState(); 791 767 792 768 $encoding = null; 793 - if ($this->characterEncoding) { 769 + 770 + $character_encoding = $viewstate->getCharacterEncoding(); 771 + if ($character_encoding) { 794 772 // We are forcing this changeset to be interpreted with a specific 795 773 // character encoding, so force all the hunks into that encoding and 796 774 // propagate it to the renderer. 797 - $encoding = $this->characterEncoding; 775 + $encoding = $character_encoding; 798 776 foreach ($this->changeset->getHunks() as $hunk) { 799 - $hunk->forceEncoding($this->characterEncoding); 777 + $hunk->forceEncoding($character_encoding); 800 778 } 801 779 } else { 802 780 // We're just using the default, so tell the renderer what that is ··· 1794 1772 } 1795 1773 } 1796 1774 1797 - $engine_key = $this->getDocumentEngineKey(); 1775 + $viewstate = $this->getViewState(); 1776 + 1777 + $engine_key = $viewstate->getDocumentEngineKey(); 1798 1778 if (strlen($engine_key)) { 1799 1779 if (isset($shared_engines[$engine_key])) { 1800 1780 $document_engine = $shared_engines[$engine_key]; ··· 1893 1873 } 1894 1874 1895 1875 return array($old_file, $new_file); 1876 + } 1877 + 1878 + public function newChangesetResponse() { 1879 + // NOTE: This has to happen first because it has side effects. Yuck. 1880 + $rendered_changeset = $this->renderChangeset(); 1881 + 1882 + $renderer = $this->getRenderer(); 1883 + $renderer_key = $renderer->getRendererKey(); 1884 + 1885 + $viewstate = $this->getViewState(); 1886 + 1887 + $undo_templates = $renderer->renderUndoTemplates(); 1888 + foreach ($undo_templates as $key => $undo_template) { 1889 + $undo_templates[$key] = hsprintf('%s', $undo_template); 1890 + } 1891 + 1892 + $state = array( 1893 + 'undoTemplates' => $undo_templates, 1894 + 'rendererKey' => $renderer_key, 1895 + 'highlight' => $viewstate->getHighlightLanguage(), 1896 + 'characterEncoding' => $viewstate->getCharacterEncoding(), 1897 + 'documentEngine' => $viewstate->getDocumentEngineKey(), 1898 + ); 1899 + 1900 + return id(new PhabricatorChangesetResponse()) 1901 + ->setRenderedChangeset($rendered_changeset) 1902 + ->setChangesetState($state); 1896 1903 } 1897 1904 1898 1905 }
+27 -27
src/applications/differential/view/DifferentialChangesetDetailView.php
··· 11 11 private $renderURI; 12 12 private $renderingRef; 13 13 private $autoload; 14 - private $loaded; 15 - private $renderer; 16 14 private $repository; 17 15 private $diff; 16 + private $changesetResponse; 18 17 19 18 public function setAutoload($autoload) { 20 19 $this->autoload = $autoload; ··· 25 24 return $this->autoload; 26 25 } 27 26 28 - public function setLoaded($loaded) { 29 - $this->loaded = $loaded; 27 + public function setRenderingRef($rendering_ref) { 28 + $this->renderingRef = $rendering_ref; 30 29 return $this; 31 30 } 32 31 33 - public function getLoaded() { 34 - return $this->loaded; 32 + public function getRenderingRef() { 33 + return $this->renderingRef; 35 34 } 36 35 37 - public function setRenderingRef($rendering_ref) { 38 - $this->renderingRef = $rendering_ref; 36 + public function setChangesetResponse(PhabricatorChangesetResponse $response) { 37 + $this->changesetResponse = $response; 39 38 return $this; 40 39 } 41 40 42 - public function getRenderingRef() { 43 - return $this->renderingRef; 41 + public function getChangesetResponse() { 42 + return $this->changesetResponse; 44 43 } 45 44 46 45 public function setRenderURI($render_uri) { ··· 72 71 return $this; 73 72 } 74 73 75 - public function setRenderer($renderer) { 76 - $this->renderer = $renderer; 77 - return $this; 78 - } 79 - 80 - public function getRenderer() { 81 - return $this->renderer; 82 - } 83 - 84 74 public function getID() { 85 75 if (!$this->id) { 86 76 $this->id = celerity_generate_unique_node_id(); ··· 139 129 $icon = id(new PHUIIconView()) 140 130 ->setIcon($display_icon); 141 131 142 - $renderer = DifferentialChangesetHTMLRenderer::getHTMLRendererByKey( 143 - $this->getRenderer()); 144 - 145 132 $changeset_id = $this->changeset->getID(); 146 133 147 134 $vs_id = $this->getVsChangesetID(); ··· 180 167 ), 181 168 $file_part); 182 169 170 + $response = $this->getChangesetResponse(); 171 + if ($response) { 172 + $is_loaded = true; 173 + $changeset_markup = $response->getRenderedChangeset(); 174 + $changeset_state = $response->getChangesetState(); 175 + } else { 176 + $is_loaded = false; 177 + $changeset_markup = null; 178 + $changeset_state = null; 179 + } 180 + 183 181 return javelin_tag( 184 182 'div', 185 183 array( ··· 188 186 'left' => $left_id, 189 187 'right' => $right_id, 190 188 'renderURI' => $this->getRenderURI(), 191 - 'highlight' => null, 192 - 'renderer' => $this->getRenderer(), 193 189 'ref' => $this->getRenderingRef(), 194 190 'autoload' => $this->getAutoload(), 195 - 'loaded' => $this->getLoaded(), 196 - 'undoTemplates' => hsprintf('%s', $renderer->renderUndoTemplates()), 197 191 'displayPath' => hsprintf('%s', $display_parts), 198 192 'path' => $display_filename, 199 193 'icon' => $display_icon, ··· 201 195 202 196 'editorURI' => $this->getEditorURI(), 203 197 'editorConfigureURI' => $this->getEditorConfigureURI(), 198 + 199 + 'loaded' => $is_loaded, 200 + 'changesetState' => $changeset_state, 204 201 ), 205 202 'class' => $class, 206 203 'id' => $id, ··· 225 222 'class' => 'changeset-view-content', 226 223 'sigil' => 'changeset-view-content', 227 224 ), 228 - $this->renderChildren()), 225 + array( 226 + $changeset_markup, 227 + $this->renderChildren(), 228 + )), 229 229 )); 230 230 } 231 231
+5 -8
src/applications/differential/view/DifferentialChangesetListView.php
··· 153 153 154 154 $changesets = $this->changesets; 155 155 156 - $renderer = DifferentialChangesetParser::getDefaultRendererForViewer( 157 - $viewer); 158 - 159 156 $repository = $this->getRepository(); 160 157 $diff = $this->getDiff(); 161 158 ··· 167 164 $ref = $this->references[$key]; 168 165 169 166 $detail = id(new DifferentialChangesetDetailView()) 170 - ->setUser($viewer); 167 + ->setViewer($viewer); 171 168 172 169 if ($repository) { 173 170 $detail->setRepository($repository); ··· 193 190 $detail->setRenderingRef($ref); 194 191 195 192 $detail->setRenderURI($this->renderURI); 196 - $detail->setRenderer($renderer); 197 193 198 - if ($this->getParser()) { 199 - $detail->appendChild($this->getParser()->renderChangeset()); 200 - $detail->setLoaded(true); 194 + $parser = $this->getParser(); 195 + if ($parser) { 196 + $response = $parser->newChangesetResponse(); 197 + $detail->setChangesetResponse($response); 201 198 } else { 202 199 $detail->setAutoload(isset($this->visibleChangesets[$key])); 203 200 if (isset($this->visibleChangesets[$key])) {
+1 -5
src/applications/diffusion/controller/DiffusionDiffController.php
··· 79 79 'action' => 'rendering-ref', 80 80 ))); 81 81 82 - $parser->readParametersFromRequest($request); 83 - 84 82 $coverage = $drequest->loadCoverage(); 85 83 if ($coverage) { 86 84 $parser->setCoverage($coverage); ··· 132 130 $parser->setRange($range_s, $range_e); 133 131 $parser->setMask($mask); 134 132 135 - return id(new PhabricatorChangesetResponse()) 136 - ->setRenderedChangeset($parser->renderChangeset()) 137 - ->setUndoTemplates($parser->getRenderer()->renderUndoTemplates()); 133 + return $parser->newChangesetResponse(); 138 134 } 139 135 }
+16 -12
src/infrastructure/diff/PhabricatorChangesetResponse.php
··· 4 4 5 5 private $renderedChangeset; 6 6 private $coverage; 7 - private $undoTemplates; 7 + private $changesetState; 8 8 9 9 public function setRenderedChangeset($rendered_changeset) { 10 10 $this->renderedChangeset = $rendered_changeset; 11 11 return $this; 12 12 } 13 13 14 - public function setCoverage($coverage) { 15 - $this->coverage = $coverage; 16 - return $this; 14 + public function getRenderedChangeset() { 15 + return $this->renderedChangeset; 17 16 } 18 17 19 - public function setUndoTemplates($undo_templates) { 20 - $this->undoTemplates = $undo_templates; 18 + public function setCoverage($coverage) { 19 + $this->coverage = $coverage; 21 20 return $this; 22 21 } 23 22 ··· 27 26 28 27 public function reduceProxyResponse() { 29 28 $content = array( 30 - 'changeset' => $this->renderedChangeset, 31 - ); 29 + 'changeset' => $this->getRenderedChangeset(), 30 + ) + $this->getChangesetState(); 32 31 33 32 if ($this->coverage) { 34 33 $content['coverage'] = $this->coverage; 35 34 } 36 35 37 - if ($this->undoTemplates) { 38 - $content['undoTemplates'] = $this->undoTemplates; 39 - } 36 + return $this->getProxy()->setContent($content); 37 + } 40 38 41 - return $this->getProxy()->setContent($content); 39 + public function setChangesetState(array $state) { 40 + $this->changesetState = $state; 41 + return $this; 42 + } 43 + 44 + public function getChangesetState() { 45 + return $this->changesetState; 42 46 } 43 47 44 48 }
+40
src/infrastructure/diff/viewstate/PhabricatorChangesetViewState.php
··· 4 4 extends Phobject { 5 5 6 6 private $highlightLanguage; 7 + private $characterEncoding; 8 + private $documentEngineKey; 9 + private $rendererKey; 10 + private $defaultDeviceRendererKey; 7 11 8 12 public function setHighlightLanguage($highlight_language) { 9 13 $this->highlightLanguage = $highlight_language; ··· 12 16 13 17 public function getHighlightLanguage() { 14 18 return $this->highlightLanguage; 19 + } 20 + 21 + public function setCharacterEncoding($character_encoding) { 22 + $this->characterEncoding = $character_encoding; 23 + return $this; 24 + } 25 + 26 + public function getCharacterEncoding() { 27 + return $this->characterEncoding; 28 + } 29 + 30 + public function setDocumentEngineKey($document_engine_key) { 31 + $this->documentEngineKey = $document_engine_key; 32 + return $this; 33 + } 34 + 35 + public function getDocumentEngineKey() { 36 + return $this->documentEngineKey; 37 + } 38 + 39 + public function setRendererKey($renderer_key) { 40 + $this->rendererKey = $renderer_key; 41 + return $this; 42 + } 43 + 44 + public function getRendererKey() { 45 + return $this->rendererKey; 46 + } 47 + 48 + public function setDefaultDeviceRendererKey($renderer_key) { 49 + $this->defaultDeviceRendererKey = $renderer_key; 50 + return $this; 51 + } 52 + 53 + public function getDefaultDeviceRendererKey() { 54 + return $this->defaultDeviceRendererKey; 15 55 } 16 56 17 57 }
+33 -1
src/infrastructure/diff/viewstate/PhabricatorChangesetViewStateEngine.php
··· 41 41 $this->setStorage($storage); 42 42 43 43 $highlight = $request->getStr('highlight'); 44 - if ($highlight !== null && strlen($highlight)) { 44 + if ($highlight !== null) { 45 45 $this->setChangesetProperty('highlight', $highlight); 46 + } 47 + 48 + $encoding = $request->getStr('encoding'); 49 + if ($encoding !== null) { 50 + $this->setChangesetProperty('encoding', $encoding); 51 + } 52 + 53 + $engine = $request->getStr('engine'); 54 + if ($engine !== null) { 55 + $this->setChangesetProperty('engine', $engine); 56 + } 57 + 58 + $renderer = $request->getStr('renderer'); 59 + if ($renderer !== null) { 60 + $this->setChangesetProperty('renderer', $renderer); 46 61 } 47 62 48 63 $this->saveViewStateStorage(); ··· 51 66 52 67 $highlight_language = $this->getChangesetProperty('highlight'); 53 68 $state->setHighlightLanguage($highlight_language); 69 + 70 + $encoding = $this->getChangesetProperty('encoding'); 71 + $state->setCharacterEncoding($encoding); 72 + 73 + $document_engine = $this->getChangesetProperty('engine'); 74 + $state->setDocumentEngineKey($document_engine); 75 + 76 + $renderer = $this->getChangesetProperty('renderer'); 77 + $state->setRendererKey($renderer); 78 + 79 + // This is the client-selected default renderer based on viewport 80 + // dimensions. 81 + 82 + $device_key = $request->getStr('device'); 83 + if ($device_key !== null && strlen($device_key)) { 84 + $state->setDefaultDeviceRendererKey($device_key); 85 + } 54 86 55 87 return $state; 56 88 }
+41 -48
webroot/rsrc/js/application/diff/DiffChangeset.js
··· 22 22 23 23 this._renderURI = data.renderURI; 24 24 this._ref = data.ref; 25 - this._renderer = data.renderer; 26 - this._highlight = data.highlight; 27 - this._documentEngine = data.documentEngine; 28 - this._encoding = data.encoding; 29 25 this._loaded = data.loaded; 30 26 this._treeNodeID = data.treeNodeID; 31 27 ··· 39 35 this._editorConfigureURI = data.editorConfigureURI; 40 36 41 37 this._inlines = []; 38 + 39 + if (data.changesetState) { 40 + this._loadChangesetState(data.changesetState); 41 + } 42 42 }, 43 43 44 44 members: { ··· 49 49 50 50 _renderURI: null, 51 51 _ref: null, 52 - _renderer: null, 52 + _rendererKey: null, 53 53 _highlight: null, 54 54 _documentEngine: null, 55 - _encoding: null, 55 + _characterEncoding: null, 56 56 _undoTemplates: null, 57 57 58 58 _leftID: null, ··· 187 187 * 188 188 * @return this 189 189 */ 190 - reload: function() { 190 + reload: function(state) { 191 191 this._loaded = true; 192 192 this._sequence++; 193 193 194 - var params = this._getViewParameters(); 194 + var params = this._getViewParameters(state); 195 195 var pht = this.getChangesetList().getTranslations(); 196 196 197 197 var workflow = new JX.Workflow(this._renderURI, params) ··· 321 321 /** 322 322 * Get parameters which define the current rendering options. 323 323 */ 324 - _getViewParameters: function() { 325 - return { 324 + _getViewParameters: function(state) { 325 + var parameters = { 326 326 ref: this._ref, 327 - renderer: this.getRenderer() || '', 328 - highlight: this._highlight || '', 329 - engine: this._documentEngine || '', 330 - encoding: this._encoding || '' 327 + device: this._getDefaultDeviceRenderer() 331 328 }; 329 + 330 + if (state) { 331 + JX.copy(parameters, state); 332 + } 333 + 334 + return parameters; 332 335 }, 333 336 334 337 /** ··· 344 347 return JX.Router.getInstance().getRoutableByKey(this._getRoutableKey()); 345 348 }, 346 349 347 - setRenderer: function(renderer) { 348 - this._renderer = renderer; 349 - return this; 350 + getRendererKey: function() { 351 + return this._rendererKey; 350 352 }, 351 353 352 - getRenderer: function() { 353 - if (this._renderer !== null) { 354 - return this._renderer; 355 - } 356 - 354 + _getDefaultDeviceRenderer: function() { 357 355 // NOTE: If you load the page at one device resolution and then resize to 358 356 // a different one we don't re-render the diffs, because it's a 359 357 // complicated mess and you could lose inline comments, cursor positions, ··· 365 363 return this._undoTemplates; 366 364 }, 367 365 368 - setEncoding: function(encoding) { 369 - this._encoding = encoding; 370 - return this; 371 - }, 372 - 373 - getEncoding: function() { 374 - return this._encoding; 375 - }, 376 - 377 - setHighlight: function(highlight) { 378 - this._highlight = highlight; 379 - return this; 366 + getCharacterEncoding: function() { 367 + return this._characterEncoding; 380 368 }, 381 369 382 370 getHighlight: function() { 383 371 return this._highlight; 384 - }, 385 - 386 - setDocumentEngine: function(engine) { 387 - this._documentEngine = engine; 388 372 }, 389 373 390 374 getDocumentEngine: function(engine) { ··· 614 598 _onchangesetresponse: function(response) { 615 599 // Code shared by autoload and context responses. 616 600 617 - if (response.coverage) { 618 - for (var k in response.coverage) { 601 + this._loadChangesetState(response); 602 + 603 + JX.Stratcom.invoke('differential-inline-comment-refresh'); 604 + 605 + this._rebuildAllInlines(); 606 + 607 + JX.Stratcom.invoke('resize'); 608 + }, 609 + 610 + _loadChangesetState: function(state) { 611 + if (state.coverage) { 612 + for (var k in state.coverage) { 619 613 try { 620 - JX.DOM.replace(JX.$(k), JX.$H(response.coverage[k])); 614 + JX.DOM.replace(JX.$(k), JX.$H(state.coverage[k])); 621 615 } catch (ignored) { 622 616 // Not terribly important. 623 617 } 624 618 } 625 619 } 626 620 627 - if (response.undoTemplates) { 628 - this._undoTemplates = response.undoTemplates; 621 + if (state.undoTemplates) { 622 + this._undoTemplates = state.undoTemplates; 629 623 } 630 624 631 - JX.Stratcom.invoke('differential-inline-comment-refresh'); 632 - 633 - this._rebuildAllInlines(); 634 - 635 - JX.Stratcom.invoke('resize'); 625 + this._rendererKey = state.rendererKey; 626 + this._highlight = state.highlight; 627 + this._characterEncoding = state.characterEncoding; 628 + this._documentEngine = state.documentEngine; 636 629 }, 637 630 638 631 _getContentFrame: function() {
+9 -11
webroot/rsrc/js/application/diff/DiffChangesetList.js
··· 798 798 } 799 799 } 800 800 801 - var renderer = changeset.getRenderer(); 801 + var renderer = changeset.getRendererKey(); 802 802 if (renderer == '1up') { 803 803 renderer = '2up'; 804 804 } else { 805 805 renderer = '1up'; 806 806 } 807 - changeset.setRenderer(renderer); 807 + changeset.reload({renderer: renderer}); 808 + } else { 809 + changeset.reload(); 808 810 } 809 - changeset.reload(); 810 811 811 812 e.prevent(); 812 813 menu.close(); ··· 818 819 .setName(pht('Change Text Encoding...')) 819 820 .setHandler(function(e) { 820 821 var params = { 821 - encoding: changeset.getEncoding() 822 + encoding: changeset.getCharacterEncoding() 822 823 }; 823 824 824 825 new JX.Workflow('/services/encoding/', params) 825 826 .setHandler(function(r) { 826 - changeset.setEncoding(r.encoding); 827 - changeset.reload(); 827 + changeset.reload({encoding: r.encoding}); 828 828 }) 829 829 .start(); 830 830 ··· 843 843 844 844 new JX.Workflow('/services/highlight/', params) 845 845 .setHandler(function(r) { 846 - changeset.setHighlight(r.highlight); 847 - changeset.reload(); 846 + changeset.reload({highlight: r.highlight}); 848 847 }) 849 848 .start(); 850 849 ··· 863 862 864 863 new JX.Workflow('/services/viewas/', params) 865 864 .setHandler(function(r) { 866 - changeset.setDocumentEngine(r.engine); 867 - changeset.reload(); 865 + changeset.reload({engine: r.engine}); 868 866 }) 869 867 .start(); 870 868 ··· 917 915 engine_item.setDisabled(!changeset.isLoaded()); 918 916 919 917 if (changeset.isLoaded()) { 920 - if (changeset.getRenderer() == '2up') { 918 + if (changeset.getRendererKey() == '2up') { 921 919 up_item 922 920 .setIcon('fa-list-alt') 923 921 .setName(pht('View Unified'));
+1 -1
webroot/rsrc/js/application/diff/DiffInline.js
··· 461 461 op: operation, 462 462 id: this._id, 463 463 on_right: ((this.getDisplaySide() == 'right') ? 1 : 0), 464 - renderer: this.getChangeset().getRenderer(), 464 + renderer: this.getChangeset().getRendererKey(), 465 465 number: this.getLineNumber(), 466 466 length: this.getLineLength(), 467 467 is_new: this.isNewFile(),