Page MenuHomePhabricator

D21152.diff
No OneTemporary

D21152.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -12,7 +12,7 @@
'core.pkg.css' => 'a4a2417c',
'core.pkg.js' => '4355a8d3',
'differential.pkg.css' => '607c84be',
- 'differential.pkg.js' => 'e40c5192',
+ 'differential.pkg.js' => '688775a9',
'diffusion.pkg.css' => '42c75c37',
'diffusion.pkg.js' => 'a98c0bf7',
'maniphest.pkg.css' => '35995d6d',
@@ -378,9 +378,11 @@
'rsrc/js/application/dashboard/behavior-dashboard-move-panels.js' => 'a2ab19be',
'rsrc/js/application/dashboard/behavior-dashboard-query-panel-select.js' => '1e413dc9',
'rsrc/js/application/dashboard/behavior-dashboard-tab-panel.js' => '0116d3e8',
- 'rsrc/js/application/diff/DiffChangeset.js' => '5a4e4a3b',
- 'rsrc/js/application/diff/DiffChangesetList.js' => '3ac694dd',
+ 'rsrc/js/application/diff/DiffChangeset.js' => 'd1eda7b4',
+ 'rsrc/js/application/diff/DiffChangesetList.js' => '469beba0',
'rsrc/js/application/diff/DiffInline.js' => '16e97ebc',
+ 'rsrc/js/application/diff/DiffPathView.js' => 'e5166692',
+ 'rsrc/js/application/diff/DiffTreeView.js' => '4055adeb',
'rsrc/js/application/diff/behavior-preview-link.js' => 'f51e9c17',
'rsrc/js/application/differential/behavior-diff-radios.js' => '925fe8cd',
'rsrc/js/application/differential/behavior-populate.js' => 'b86ef6c2',
@@ -778,9 +780,11 @@
'phabricator-darklog' => '3b869402',
'phabricator-darkmessage' => '26cd4b73',
'phabricator-dashboard-css' => '5a205b9d',
- 'phabricator-diff-changeset' => '5a4e4a3b',
- 'phabricator-diff-changeset-list' => '3ac694dd',
+ 'phabricator-diff-changeset' => 'd1eda7b4',
+ 'phabricator-diff-changeset-list' => '469beba0',
'phabricator-diff-inline' => '16e97ebc',
+ 'phabricator-diff-path-view' => 'e5166692',
+ 'phabricator-diff-tree-view' => '4055adeb',
'phabricator-drag-and-drop-file-upload' => '4370900d',
'phabricator-draggable-list' => '0169e425',
'phabricator-fatal-config-template-css' => '20babf50',
@@ -1240,10 +1244,6 @@
'trigger-rule',
'trigger-rule-type',
),
- '3ac694dd' => array(
- 'javelin-install',
- 'phuix-button-view',
- ),
'3ae89b20' => array(
'phui-workcard-view-css',
),
@@ -1267,6 +1267,9 @@
'phabricator-drag-and-drop-file-upload',
'phabricator-draggable-list',
),
+ '4055adeb' => array(
+ 'javelin-dom',
+ ),
'407ee861' => array(
'javelin-behavior',
'javelin-uri',
@@ -1316,6 +1319,11 @@
'javelin-util',
'phabricator-busy',
),
+ '469beba0' => array(
+ 'javelin-install',
+ 'phuix-button-view',
+ 'phabricator-diff-tree-view',
+ ),
'47a0728b' => array(
'javelin-behavior',
'javelin-dom',
@@ -1466,17 +1474,6 @@
'javelin-dom',
'javelin-history',
),
- '5a4e4a3b' => array(
- 'javelin-dom',
- 'javelin-util',
- 'javelin-stratcom',
- 'javelin-install',
- 'javelin-workflow',
- 'javelin-router',
- 'javelin-behavior-device',
- 'javelin-vector',
- 'phabricator-diff-inline',
- ),
'5a6f6a06' => array(
'javelin-behavior',
'javelin-quicksand',
@@ -2099,6 +2096,18 @@
'javelin-workflow',
'javelin-util',
),
+ 'd1eda7b4' => array(
+ 'javelin-dom',
+ 'javelin-util',
+ 'javelin-stratcom',
+ 'javelin-install',
+ 'javelin-workflow',
+ 'javelin-router',
+ 'javelin-behavior-device',
+ 'javelin-vector',
+ 'phabricator-diff-inline',
+ 'phabricator-diff-path-view',
+ ),
'd3799cb4' => array(
'javelin-install',
),
@@ -2125,6 +2134,9 @@
'javelin-dom',
'phuix-dropdown-menu',
),
+ 'e5166692' => array(
+ 'javelin-dom',
+ ),
'e5bdb730' => array(
'javelin-behavior',
'javelin-stratcom',
diff --git a/src/applications/differential/view/DifferentialChangesetDetailView.php b/src/applications/differential/view/DifferentialChangesetDetailView.php
--- a/src/applications/differential/view/DifferentialChangesetDetailView.php
+++ b/src/applications/differential/view/DifferentialChangesetDetailView.php
@@ -178,6 +178,9 @@
$changeset_state = null;
}
+ $path_parts = trim($display_filename, '/');
+ $path_parts = explode('/', $path_parts);
+
return javelin_tag(
'div',
array(
@@ -189,9 +192,9 @@
'ref' => $this->getRenderingRef(),
'autoload' => $this->getAutoload(),
'displayPath' => hsprintf('%s', $display_parts),
- 'path' => $display_filename,
'icon' => $display_icon,
'treeNodeID' => 'tree-node-'.$changeset->getAnchorName(),
+ 'pathParts' => $path_parts,
'editorURI' => $this->getEditorURI(),
'editorConfigureURI' => $this->getEditorConfigureURI(),
diff --git a/webroot/rsrc/js/application/diff/DiffChangeset.js b/webroot/rsrc/js/application/diff/DiffChangeset.js
--- a/webroot/rsrc/js/application/diff/DiffChangeset.js
+++ b/webroot/rsrc/js/application/diff/DiffChangeset.js
@@ -9,10 +9,10 @@
* javelin-behavior-device
* javelin-vector
* phabricator-diff-inline
+ * phabricator-diff-path-view
* @javelin
*/
-
JX.install('DiffChangeset', {
construct : function(node) {
@@ -29,6 +29,7 @@
this._rightID = data.right;
this._displayPath = JX.$H(data.displayPath);
+ this._pathParts = data.pathParts;
this._icon = data.icon;
this._editorURI = data.editorURI;
@@ -70,6 +71,7 @@
_editorURI: null,
_editorConfigureURI: null,
+ _pathView: null,
getEditorURI: function() {
return this._editorURI;
@@ -891,6 +893,21 @@
_onundo: function(e) {
e.kill();
this.toggleVisibility();
+ },
+
+ getPathView: function() {
+ if (!this._pathView) {
+ this._pathView = new JX.DiffPathView()
+ .setChangeset(this)
+ .setPath(this._pathParts);
+ }
+
+ return this._pathView;
+ },
+
+ select: function(scroll) {
+ this.getChangesetList().selectChangeset(this, scroll);
+ return this;
}
},
diff --git a/webroot/rsrc/js/application/diff/DiffChangesetList.js b/webroot/rsrc/js/application/diff/DiffChangesetList.js
--- a/webroot/rsrc/js/application/diff/DiffChangesetList.js
+++ b/webroot/rsrc/js/application/diff/DiffChangesetList.js
@@ -2,6 +2,7 @@
* @provides phabricator-diff-changeset-list
* @requires javelin-install
* phuix-button-view
+ * phabricator-diff-tree-view
* @javelin
*/
@@ -640,6 +641,25 @@
};
},
+ selectChangeset: function(changeset, scroll) {
+ var items = this._getSelectableItems();
+
+ var cursor = null;
+ for (var ii = 0; ii < items.length; ii++) {
+ var item = items[ii];
+ if (changeset === item.target) {
+ cursor = ii;
+ break;
+ }
+ }
+
+ if (cursor !== null) {
+ this._setSelectionState(items[cursor], true);
+ }
+
+ return this;
+ },
+
_setSelectionState: function(item, scroll) {
this._cursorItem = item;
this._redrawSelection(scroll);
@@ -1467,10 +1487,18 @@
var node = this._getBannerNode();
var changeset = this._getVisibleChangeset();
+ var tree = this._getTreeView();
+ var formation = this.getFormationView();
if (!changeset) {
this._bannerChangeset = null;
JX.DOM.remove(node);
+ tree.setSelectedPath(null);
+
+ if (formation) {
+ formation.repaint();
+ }
+
return;
}
@@ -1481,6 +1509,14 @@
}
this._bannerChangeset = changeset;
+ var paths = tree.getPaths();
+ for (var ii = 0; ii < paths.length; ii++) {
+ var path = paths[ii];
+ if (path.getChangeset() === changeset) {
+ tree.setSelectedPath(path);
+ }
+ }
+
var inlines = this._getInlinesByType();
var unsaved = inlines.unsaved;
@@ -1586,6 +1622,10 @@
JX.DOM.setContent(node, [buttons_view, path_view]);
document.body.appendChild(node);
+
+ if (formation) {
+ formation.repaint();
+ }
},
_getInlinesByType: function() {
@@ -1958,6 +1998,20 @@
return null;
},
+ _getTreeView: function() {
+ if (!this._treeView) {
+ var tree = new JX.DiffTreeView();
+
+ for (var ii = 0; ii < this._changesets.length; ii++) {
+ var changeset = this._changesets[ii];
+ tree.addPath(changeset.getPathView());
+ }
+
+ this._treeView = tree;
+ }
+ return this._treeView;
+ },
+
_redrawFiletree : function() {
var formation = this.getFormationView();
@@ -1970,15 +2024,8 @@
var flank_body = flank.getBodyNode();
- var items = [];
- for (var ii = 0; ii < this._changesets.length; ii++) {
- var changeset = this._changesets[ii];
-
- var node = JX.$N('div', {}, changeset.getDisplayPath());
- items.push(node);
- }
-
- JX.DOM.setContent(flank_body, items);
+ var tree = this._getTreeView();
+ JX.DOM.setContent(flank_body, tree.getNode());
}
}
diff --git a/webroot/rsrc/js/application/diff/DiffPathView.js b/webroot/rsrc/js/application/diff/DiffPathView.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/application/diff/DiffPathView.js
@@ -0,0 +1,83 @@
+/**
+ * @provides phabricator-diff-path-view
+ * @requires javelin-dom
+ * @javelin
+ */
+
+JX.install('DiffPathView', {
+
+ construct: function() {
+ },
+
+ properties: {
+ changeset: null
+ },
+
+ members: {
+ _node: null,
+ _path: null,
+ _depth: 0,
+ _selected: false,
+
+ getNode: function() {
+ if (!this._node) {
+ this._node = JX.$N('li');
+
+ var onclick = JX.bind(this, this._onclick);
+ JX.DOM.listen(this._node, 'click', null, onclick);
+ }
+ return this._node;
+ },
+
+ setPath: function(path) {
+ this._path = path;
+ this._redraw();
+ return this;
+ },
+
+ getPath: function() {
+ return this._path;
+ },
+
+ setDepth: function(depth) {
+ this._depth = depth;
+ this._redraw();
+ return this;
+ },
+
+ setIsSelected: function(selected) {
+ this._selected = selected;
+ this._redraw();
+ return this;
+ },
+
+ _onclick: function(e) {
+ if (!e.isNormalClick()) {
+ return;
+ }
+
+ var changeset = this.getChangeset();
+ if (changeset) {
+ changeset.select(true);
+ }
+
+ e.kill();
+ },
+
+ _redraw: function() {
+ var node = this.getNode();
+
+ node.style.paddingLeft = (8 * this._depth) + 'px';
+
+ var display = this._path[this._path.length - 1];
+
+ if (this._selected) {
+ display = ['*', display];
+ }
+
+ JX.DOM.setContent(node, display);
+ }
+
+ }
+
+});
diff --git a/webroot/rsrc/js/application/diff/DiffTreeView.js b/webroot/rsrc/js/application/diff/DiffTreeView.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/application/diff/DiffTreeView.js
@@ -0,0 +1,159 @@
+/**
+ * @provides phabricator-diff-tree-view
+ * @requires javelin-dom
+ * @javelin
+ */
+
+JX.install('DiffTreeView', {
+
+ construct: function() {
+ this._keys = [];
+ this._tree = this._newTreeNode(null, [], 0);
+ this._nodes = {};
+ this._paths = [];
+ },
+
+ members: {
+ _node: null,
+ _keys: null,
+ _tree: null,
+ _nodes: null,
+ _dirty: false,
+ _paths: null,
+ _selectedPath: null,
+
+ getNode: function() {
+ if (!this._node) {
+ this._node = JX.$N('ul');
+ }
+
+ if (this._dirty) {
+ this.redraw();
+ }
+
+ return this._node;
+ },
+
+ addPath: function(path) {
+ this._paths.push(path);
+
+ var tree = this._getTree(this._tree, path.getPath(), 0);
+ tree.pathObject = path;
+
+ this._dirty = true;
+
+ return this;
+ },
+
+ getPaths: function() {
+ return this._paths;
+ },
+
+ setSelectedPath: function(path) {
+ if (this._selectedPath) {
+ this._selectedPath.setIsSelected(false);
+ this._selectedPath = null;
+ }
+
+ if (path) {
+ path.setIsSelected(true);
+ }
+
+ this._selectedPath = path;
+
+ return this;
+ },
+
+ redraw: function() {
+ if (!this._dirty) {
+ return;
+ }
+ this._dirty = false;
+
+ var ii;
+
+ // For nodes which don't have a path object yet, build one.
+ var tree;
+ var trees = [];
+ for (ii = 0; ii < this._keys.length; ii++) {
+ var key = this._keys[ii];
+ tree = this._nodes[key];
+ var path = tree.pathObject;
+
+ if (!path) {
+ path = new JX.DiffPathView()
+ .setPath(tree.parts);
+ tree.pathObject = path;
+ }
+
+ trees.push(tree);
+ }
+
+ for (ii = 0; ii < trees.length; ii++) {
+ tree = trees[ii];
+
+ if (!tree.parent) {
+ tree.depth = 0;
+ } else {
+ tree.depth = tree.parent.depth + 1;
+ }
+
+ tree.pathObject.setDepth((tree.depth - 1));
+ }
+
+ var nodes = [];
+ for (ii = 0; ii < trees.length; ii++) {
+ tree = trees[ii];
+ nodes.push(tree.pathObject.getNode());
+ }
+
+ JX.DOM.setContent(this.getNode(), nodes);
+ },
+
+ _getTree: function(root, path, ii) {
+ if (ii >= path.length) {
+ return root;
+ }
+
+ var part = path[ii];
+
+ if (!root.children.hasOwnProperty(part)) {
+ root.children[part] = this._newTreeNode(root, path, ii);
+ root.childCount++;
+ }
+
+ return this._getTree(root.children[part], path, ii + 1);
+ },
+
+ _newTreeNode: function(parent, path, ii) {
+ var key;
+ var parts;
+ if (path.length) {
+ parts = path.slice(0, ii + 1);
+ key = parts.join('/');
+ this._keys.push(key);
+ } else {
+ parts = [];
+ key = null;
+ }
+
+ var node = {
+ parent: parent,
+ nodeKey: key,
+ parts: parts,
+ children: {},
+ pathObject: null,
+ childCount: 0,
+ depth: 0
+ };
+
+ if (key !== null) {
+ this._nodes[key] = node;
+ }
+
+ return node;
+ }
+
+ }
+
+});

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 5, 4:14 AM (2 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7223535
Default Alt Text
D21152.diff (14 KB)

Event Timeline