Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/command/Commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,9 @@ define(function (require, exports, module) {
/** Closes unmodified files */
exports.CMD_GIT_CLOSE_UNMODIFIED = "git-close-unmodified-files";

/** Opens all modified/untracked files */
exports.CMD_GIT_OPEN_CHANGED_FILES = "git-open-changed-files";

/** Checks out a branch or commit */
exports.CMD_GIT_CHECKOUT = "git-checkout";

Expand Down
131 changes: 100 additions & 31 deletions src/extensions/default/Git/src/Branch.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ define(function (require, exports) {
currentEditor,
$dropdown;

let lastRenderedBranchName = null;
let $dropdownAnchor = null;

function renderList(branches) {
branches = branches.map(function (name) {
return {
Expand Down Expand Up @@ -303,6 +306,7 @@ define(function (require, exports) {
function attachCloseEvents() {
$("html").on("click", closeDropdown);
$("#project-files-container").on("scroll", closeDropdown);
$("#git-panel .table-container").on("scroll", closeDropdown);
$("#titlebar .nav").on("click", closeDropdown);

currentEditor = EditorManager.getCurrentFullEditor();
Expand All @@ -316,6 +320,7 @@ define(function (require, exports) {
function detachCloseEvents() {
$("html").off("click", closeDropdown);
$("#project-files-container").off("scroll", closeDropdown);
$("#git-panel .table-container").off("scroll", closeDropdown);
$("#titlebar .nav").off("click", closeDropdown);

if (currentEditor) {
Expand All @@ -325,22 +330,84 @@ define(function (require, exports) {
// $(window).off("keydown", keydownHook);

$dropdown = null;
$dropdownAnchor = null;
}

function _positionDropdownBelow($toggle) {
// two margins to account for the preceding project dropdown as well
const marginLeft = (parseInt($toggle.css("margin-left"), 10) * 2) || 0;

const toggleOffset = $toggle.offset();

$dropdown
.css({
left: toggleOffset.left - marginLeft + 3,
top: toggleOffset.top + $toggle.outerHeight() - 3
})
.appendTo($("body"));

// fix so it doesn't overflow the screen
const maxHeight = $dropdown.parent().height(),
height = $dropdown.height(),
topOffset = $dropdown.position().top;
if (height + topOffset >= maxHeight - 10) {
$dropdown.css("bottom", "10px");
}
}

function _positionDropdownAbove($anchor) {
const anchorOffset = $anchor.offset();

$dropdown
.css({
left: anchorOffset.left,
// #git-branch-dropdown carries a negative margin-left meant for the
// sidebar toggle alignment, neutralize it so left matches the anchor
"margin-left": 0,
// the .dropdown-menu class positions with "top: 100%", it has to be
// explicitly overridden or the bottom positioning below is over-constrained
top: "auto",
bottom: $(window).height() - anchorOffset.top + 3,
// grow upwards from the anchor instead of the default top-left origin
"transform-origin": "0 100%"
})
.appendTo($("body"));

// fix so it doesn't overflow the screen
if ($dropdown.height() >= anchorOffset.top - 10) {
$dropdown.css("top", "10px");
}

const rightOverflow = $dropdown.offset().left + $dropdown.outerWidth() - ($(window).width() - 10);
if (rightOverflow > 0) {
$dropdown.css("left", anchorOffset.left - rightOverflow);
}
}

function toggleDropdown(e) {
e.stopPropagation();
// currentTarget is only valid while the event is being dispatched,
// so it has to be captured before the async branch listing below
const $anchor = $(e.currentTarget);

// If the dropdown is already visible, close it
// clicking the anchor that opened the dropdown closes it, clicking the
// other anchor moves the dropdown there
if ($dropdown) {
const sameAnchor = $dropdownAnchor && $dropdownAnchor[0] === $anchor[0];
closeDropdown();
return;
if (sameAnchor) {
return;
}
}

Menus.closeAll();

Git.getBranches().catch(function (err) {
ErrorHandler.showError(err, Strings.ERROR_GETTING_BRANCH_LIST);
}).then(function (branches = []) {
if ($dropdown) {
return;
}
branches = branches.reduce(function (arr, branch) {
if (!branch.currentBranch && !branch.remote) {
arr.push(branch.name);
Expand All @@ -349,25 +416,12 @@ define(function (require, exports) {
}, []);

$dropdown = $(renderList(branches));
const $toggle = $("#git-branch-dropdown-toggle");
// two margins to account for the preceding project dropdown as well
const marginLeft = (parseInt($toggle.css("margin-left"), 10) * 2) || 0;

const toggleOffset = $toggle.offset();

$dropdown
.css({
left: toggleOffset.left - marginLeft + 3,
top: toggleOffset.top + $toggle.outerHeight() - 3
})
.appendTo($("body"));

// fix so it doesn't overflow the screen
var maxHeight = $dropdown.parent().height(),
height = $dropdown.height(),
topOffset = $dropdown.position().top;
if (height + topOffset >= maxHeight - 10) {
$dropdown.css("bottom", "10px");
$dropdownAnchor = $anchor;
if ($anchor.closest("#git-panel").length) {
// the git panel sits at the bottom of the screen, open upwards from there
_positionDropdownAbove($anchor);
} else {
_positionDropdownBelow($("#git-branch-dropdown-toggle"));
}

PopUpManager.addPopUp($dropdown, detachCloseEvents, true, {closeCurrentPopups: true});
Expand Down Expand Up @@ -409,10 +463,9 @@ define(function (require, exports) {
return;
}

var branchInHead = m[1],
branchInUi = $gitBranchName.text();
const branchInHead = m[1];

if (branchInHead !== branchInUi) {
if (branchInHead !== lastRenderedBranchName) {
refresh();
}
});
Expand All @@ -426,6 +479,7 @@ define(function (require, exports) {
.text("\u2026")
.parent()
.show();
Panel.setBranchName("\u2026", "");

return Git.getGitRoot().then(function (gitRoot) {
var projectRoot = Utils.getProjectRoot(),
Expand All @@ -437,9 +491,12 @@ define(function (require, exports) {
Preferences.set("currentGitRoot", projectRoot);
Preferences.set("currentGitSubfolder", "");

lastRenderedBranchName = null;
$gitBranchName
.off("click")
.text("not a git repo");
.text(Strings.GIT_NOT_A_REPO);
Panel.setBranchName(Strings.GIT_NOT_A_REPO, "");
$("#git-panel .git-panel-branch").removeClass("clickable").off("click");
Panel.disable("not-repo");

return;
Expand Down Expand Up @@ -471,17 +528,26 @@ define(function (require, exports) {

EventEmitter.emit(Events.REBASE_MERGE_MODE, mergeInfo.rebaseMode, mergeInfo.mergeMode);

var MAX_LEN = 18;
const MAX_LEN = 18;

lastRenderedBranchName = branchName;
const tooltip = StringUtils.format(Strings.ON_BRANCH, branchName);
const html = `<i class="fas fa-code-branch"></i> ${
branchName.length > MAX_LEN ? branchName.substring(0, MAX_LEN) + "\u2026" : branchName
}`;
const displayName = branchName.length > MAX_LEN
? branchName.substring(0, MAX_LEN) + "\u2026"
: branchName;
// branch names may contain characters like "<", so set them
// as text and never as html
$gitBranchName
.html(html)
.text(" " + displayName)
.prepend('<i class="fas fa-code-branch"></i>')
.attr("title", tooltip)
.off("click")
.on("click", toggleDropdown);
Panel.setBranchName(displayName, tooltip);
$("#git-panel .git-panel-branch")
.addClass("clickable")
.off("click")
.on("click", toggleDropdown);
Panel.enable();

}).catch(function (err) {
Expand All @@ -490,9 +556,12 @@ define(function (require, exports) {

}).catch(function (ex) {
if (ErrorHandler.contains(ex, "unknown revision")) {
lastRenderedBranchName = null;
$gitBranchName
.off("click")
.text("no branch");
.text(Strings.GIT_NO_BRANCH);
Panel.setBranchName(Strings.GIT_NO_BRANCH, "");
$("#git-panel .git-panel-branch").removeClass("clickable").off("click");
Panel.enable();
} else {
throw ex;
Expand Down
1 change: 1 addition & 0 deletions src/extensions/default/Git/src/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ define(function (require, exports) {
exports.CMD_GIT_CLONE_WITH_URL = Commands.CMD_GIT_CLONE_WITH_URL;
exports.CMD_GIT_SETTINGS_COMMAND_ID = Commands.CMD_GIT_SETTINGS_COMMAND_ID;
exports.CMD_GIT_CLOSE_UNMODIFIED = Commands.CMD_GIT_CLOSE_UNMODIFIED;
exports.CMD_GIT_OPEN_CHANGED_FILES = Commands.CMD_GIT_OPEN_CHANGED_FILES;
exports.CMD_GIT_CHECKOUT = Commands.CMD_GIT_CHECKOUT;
exports.CMD_GIT_RESET_HARD = Commands.CMD_GIT_RESET_HARD;
exports.CMD_GIT_RESET_SOFT = Commands.CMD_GIT_RESET_SOFT;
Expand Down
4 changes: 4 additions & 0 deletions src/extensions/default/Git/src/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ define(function (require, exports) {
Constants.CMD_GIT_RESET_SOFT,

// "More options" context menu commands
Constants.CMD_GIT_OPEN_CHANGED_FILES,
Constants.CMD_GIT_DISCARD_ALL_CHANGES,
Constants.CMD_GIT_UNDO_LAST_COMMIT,
Constants.CMD_GIT_TOGGLE_UNTRACKED,
Expand Down Expand Up @@ -322,6 +323,8 @@ define(function (require, exports) {
// create context menu for git more options
const optionsCmenu = Menus.registerContextMenu(Constants.GIT_PANEL_OPTIONS_CMENU);
Menus.ContextMenu.assignContextMenuToSelector(".git-more-options-btn", optionsCmenu);
optionsCmenu.addMenuItem(Constants.CMD_GIT_OPEN_CHANGED_FILES);
optionsCmenu.addMenuDivider();
optionsCmenu.addMenuItem(Constants.CMD_GIT_DISCARD_ALL_CHANGES);
optionsCmenu.addMenuItem(Constants.CMD_GIT_UNDO_LAST_COMMIT);
optionsCmenu.addMenuDivider();
Expand Down Expand Up @@ -398,6 +401,7 @@ define(function (require, exports) {
Utils.enableCommand(Constants.CMD_GIT_GOTO_NEXT_CHANGE, enabled);
Utils.enableCommand(Constants.CMD_GIT_GOTO_PREVIOUS_CHANGE, enabled);
Utils.enableCommand(Constants.CMD_GIT_CLOSE_UNMODIFIED, enabled);
Utils.enableCommand(Constants.CMD_GIT_OPEN_CHANGED_FILES, enabled);

Utils.enableCommand(Constants.CMD_GIT_AUTHORS_OF_SELECTION, enabled);
Utils.enableCommand(Constants.CMD_GIT_AUTHORS_OF_FILE, enabled);
Expand Down
71 changes: 71 additions & 0 deletions src/extensions/default/Git/src/Panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
Menus = brackets.getModule("command/Menus"),
Mustache = brackets.getModule("thirdparty/mustache/mustache"),
FindInFiles = brackets.getModule("search/FindInFiles"),
MainViewManager = brackets.getModule("view/MainViewManager"),
WorkspaceManager = brackets.getModule("view/WorkspaceManager"),
ProjectManager = brackets.getModule("project/ProjectManager"),
StringUtils = brackets.getModule("utils/StringUtils"),
Expand Down Expand Up @@ -851,6 +852,14 @@
}
}

// called by Branch.refresh() with the already truncated display name so the panel
// indicator always mirrors the sidebar one, including decorations like "main|MERGING"
function setBranchName(branchName, tooltip) {
const $branch = $gitPanel.find(".git-panel-branch");
$branch.attr("title", tooltip || "");
$branch.find(".git-branch-name").text(branchName);
}

function refreshCommitCounts() {
// Find Push and Pull buttons
var $pullBtn = $gitPanel.find(".git-pull");
Expand Down Expand Up @@ -1007,6 +1016,64 @@
});
}

const OPEN_ALL_CONFIRM_THRESHOLD = 50;

function _openChangedFiles(fileList) {
MainViewManager.addListToWorkingSet(MainViewManager.ACTIVE_PANE, fileList);
if (!MainViewManager.getCurrentlyViewedPath(MainViewManager.ACTIVE_PANE)) {
CommandManager.execute(Commands.FILE_OPEN, { fullPath: fileList[0].fullPath });
}
}

function openAllChangedFiles() {
return Git.status().then(function (files) {
files = _.filter(files, function (file) {
if (!shouldShow(file)) {
return false;
}
// deleted files no longer exist on disk, so there is nothing to open
if (file.status.indexOf(Git.FILE_STATUS.DELETED) !== -1) {

Check warning on line 1035 in src/extensions/default/Git/src/Panel.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use `.includes()`, rather than `.indexOf()`, when checking for existence.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZ9V24C0OFmXP_NXUUY5&open=AZ9V24C0OFmXP_NXUUY5&pullRequest=3022
return false;
}
// respect the "show untracked files" panel toggle
if (!showingUntracked && file.status.indexOf(Git.FILE_STATUS.UNTRACKED) !== -1) {

Check warning on line 1039 in src/extensions/default/Git/src/Panel.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use `.includes()`, rather than `.indexOf()`, when checking for existence.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZ9V24C0OFmXP_NXUUY6&open=AZ9V24C0OFmXP_NXUUY6&pullRequest=3022
return false;
}
return true;
});

if (files.length === 0) {
return;
}

const currentGitRoot = Preferences.get("currentGitRoot");
const fileList = files.map(function (file) {
return FileSystem.getFileForPath(currentGitRoot + file.file);
});

// count only the files the command would actually add, so re-running it
// when most of them are already open doesn't ask for confirmation again
const newFileCount = _.filter(fileList, function (file) {
return MainViewManager.findInAllWorkingSets(file.fullPath).length === 0;
}).length;

if (newFileCount > OPEN_ALL_CONFIRM_THRESHOLD) {
return Utils.askQuestion(Strings.CMD_OPEN_CHANGED_FILES,
StringUtils.format(Strings.OPEN_CHANGED_FILES_CONFIRM, newFileCount),
{ booleanResponse: true })
.then(function (response) {
if (response === true) {
_openChangedFiles(fileList);
}
});
}

_openChangedFiles(fileList);
}).catch(function (err) {
ErrorHandler.showError(err, Strings.ERROR_OPENING_CHANGED_FILES);
});
}

var lastCheckOneClicked = null;

function attachDefaultTableHandlers() {
Expand Down Expand Up @@ -1214,6 +1281,7 @@
const mainToolbarWidth = $mainToolbar.width();
let overFlowWidth = 540;
const breakpoints = [
{ width: 600, className: "hide-when-medium" },
{ width: overFlowWidth, className: "hide-when-small" },
{ width: 400, className: "hide-when-x-small" }
];
Expand Down Expand Up @@ -1345,6 +1413,8 @@
CommandManager.register(Strings.VIEW_AUTHORS_SELECTION, Constants.CMD_GIT_AUTHORS_OF_SELECTION, handleAuthorsSelection);
CommandManager.register(Strings.VIEW_AUTHORS_FILE, Constants.CMD_GIT_AUTHORS_OF_FILE, handleAuthorsFile);
CommandManager.register(Strings.HIDE_UNTRACKED, Constants.CMD_GIT_TOGGLE_UNTRACKED, handleToggleUntracked);
CommandManager.register(Strings.CMD_OPEN_CHANGED_FILES,
Constants.CMD_GIT_OPEN_CHANGED_FILES, openAllChangedFiles);
CommandManager.register(Strings.GIT_INIT, Constants.CMD_GIT_INIT, EventEmitter.getEmitter(Events.HANDLE_GIT_INIT));
CommandManager.register(Strings.GIT_CLONE, Constants.CMD_GIT_CLONE, EventEmitter.getEmitter(Events.HANDLE_GIT_CLONE));
CommandManager.register(Strings.GIT_SHOW_HISTORY, Constants.CMD_GIT_HISTORY_GLOBAL, ()=>{
Expand Down Expand Up @@ -1555,6 +1625,7 @@
exports.toggle = toggle;
exports.enable = enable;
exports.disable = disable;
exports.setBranchName = setBranchName;
exports.getSelectedHistoryCommit = getSelectedHistoryCommit;
exports.getPanel = function () { return $gitPanel; };

Expand Down
Loading
Loading