Skip to content

Commit fd6086b

Browse files
committed
feat: add reopen closed file in tab bar context menu
1 parent dcd0a33 commit fd6086b

File tree

4 files changed

+109
-36
lines changed

4 files changed

+109
-36
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
define(function (require, exports, module) {
2+
/**
3+
* This array's represents the current working set
4+
* It holds all the working set items that are to be displayed in the tab bar
5+
* Properties of each object:
6+
* path: {String} full path of the file
7+
* name: {String} name of the file
8+
* isFile: {Boolean} whether the file is a file or a directory
9+
* isDirty: {Boolean} whether the file is dirty
10+
* isPinned: {Boolean} whether the file is pinned
11+
* displayName: {String} name to display in the tab (may include directory info for duplicate files)
12+
*/
13+
let firstPaneWorkingSet = [];
14+
let secondPaneWorkingSet = [];
15+
16+
module.exports = {
17+
firstPaneWorkingSet,
18+
secondPaneWorkingSet
19+
};
20+
});

src/extensionsIntegrated/TabBar/main.js

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,14 @@ define(function (require, exports, module) {
99
const Commands = require("command/Commands");
1010
const DocumentManager = require("document/DocumentManager");
1111

12-
12+
const Global = require("./global");
1313
const Helper = require("./helper");
1414
const Preference = require("./preference");
1515
const MoreOptions = require("./more-options");
1616
const TabBarHTML = require("text!./html/tabbar-pane.html");
1717
const TabBarHTML2 = require("text!./html/tabbar-second-pane.html");
1818

1919

20-
/**
21-
* This array's represents the current working set
22-
* It holds all the working set items that are to be displayed in the tab bar
23-
* Properties of each object:
24-
* path: {String} full path of the file
25-
* name: {String} name of the file
26-
* isFile: {Boolean} whether the file is a file or a directory
27-
* isDirty: {Boolean} whether the file is dirty
28-
* isPinned: {Boolean} whether the file is pinned
29-
* displayName: {String} name to display in the tab (may include directory info for duplicate files)
30-
*/
31-
let firstPaneWorkingSet = [];
32-
let secondPaneWorkingSet = [];
33-
3420

3521
/**
3622
* This holds the tab bar element
@@ -48,8 +34,8 @@ define(function (require, exports, module) {
4834
* This is placed here instead of helper.js because it modifies the working sets
4935
*/
5036
function getAllFilesFromWorkingSet() {
51-
firstPaneWorkingSet = [];
52-
secondPaneWorkingSet = [];
37+
Global.firstPaneWorkingSet = [];
38+
Global.secondPaneWorkingSet = [];
5339

5440
// this gives the list of panes. When both panes are open, it will be ['first-pane', 'second-pane']
5541
const paneList = MainViewManager.getPaneIdList();
@@ -63,21 +49,36 @@ define(function (require, exports, module) {
6349
for (let i = 0; i < currFirstPaneWorkingSet.length; i++) {
6450
// MainViewManager.getWorkingSet gives the working set of the first pane,
6551
// but it has lot of details we don't need. Hence we use Helper._getRequiredDataFromEntry
66-
firstPaneWorkingSet.push(Helper._getRequiredDataFromEntry(currFirstPaneWorkingSet[i]));
52+
Global.firstPaneWorkingSet.push(Helper._getRequiredDataFromEntry(currFirstPaneWorkingSet[i]));
6753
}
6854
// if there are duplicate file names, we update the displayName to include the directory
69-
Helper._handleDuplicateFileNames(firstPaneWorkingSet);
55+
Helper._handleDuplicateFileNames(Global.firstPaneWorkingSet);
7056

7157
// check if second pane is open
7258
if (paneList.length > 1) {
7359
const currSecondPaneWorkingSet = MainViewManager.getWorkingSet(paneList[1]);
7460

7561
for (let i = 0; i < currSecondPaneWorkingSet.length; i++) {
76-
secondPaneWorkingSet.push(Helper._getRequiredDataFromEntry(currSecondPaneWorkingSet[i]));
62+
Global.secondPaneWorkingSet.push(Helper._getRequiredDataFromEntry(currSecondPaneWorkingSet[i]));
7763
}
78-
Helper._handleDuplicateFileNames(secondPaneWorkingSet);
79-
64+
Helper._handleDuplicateFileNames(Global.secondPaneWorkingSet);
8065
}
66+
67+
// Update dirty status for files in the first pane working set
68+
Global.firstPaneWorkingSet.forEach(function (entry) {
69+
const doc = DocumentManager.getOpenDocumentForPath(entry.path);
70+
if (doc) {
71+
entry.isDirty = doc.isDirty;
72+
}
73+
});
74+
75+
// Update dirty status for files in the second pane working set
76+
Global.secondPaneWorkingSet.forEach(function (entry) {
77+
const doc = DocumentManager.getOpenDocumentForPath(entry.path);
78+
if (doc) {
79+
entry.isDirty = doc.isDirty;
80+
}
81+
});
8182
}
8283
}
8384

@@ -146,38 +147,38 @@ define(function (require, exports, module) {
146147
const $firstTabBar = $('#phoenix-tab-bar');
147148
const $secondTabBar = $('#phoenix-tab-bar-2');
148149

149-
if (firstPaneWorkingSet.length === 0 && ($('#phoenix-tab-bar'))) {
150+
if (Global.firstPaneWorkingSet.length === 0 && ($('#phoenix-tab-bar'))) {
150151
Helper._hideTabBar($('#phoenix-tab-bar'), $('#tab-bar-more-options'));
151152
}
152153

153-
if (secondPaneWorkingSet.length === 0 && ($('#phoenix-tab-bar-2'))) {
154+
if (Global.secondPaneWorkingSet.length === 0 && ($('#phoenix-tab-bar-2'))) {
154155
Helper._hideTabBar($('#phoenix-tab-bar-2'), $('#tab-bar-more-options-2'));
155156
}
156157

157158
// get the count of tabs that we want to display in the tab bar (from preference settings)
158159
// from preference settings or working set whichever smaller
159-
let tabsCountP1 = Math.min(firstPaneWorkingSet.length, Preference.tabBarNumberOfTabs);
160-
let tabsCountP2 = Math.min(secondPaneWorkingSet.length, Preference.tabBarNumberOfTabs);
160+
let tabsCountP1 = Math.min(Global.firstPaneWorkingSet.length, Preference.tabBarNumberOfTabs);
161+
let tabsCountP2 = Math.min(Global.secondPaneWorkingSet.length, Preference.tabBarNumberOfTabs);
161162

162163
// the value is generally '-1', but we check for less than 0 so that it can handle edge cases gracefully
163164
// if the value is negative then we display all tabs
164165
if (Preference.tabBarNumberOfTabs < 0) {
165-
tabsCountP1 = firstPaneWorkingSet.length;
166-
tabsCountP2 = secondPaneWorkingSet.length;
166+
tabsCountP1 = Global.firstPaneWorkingSet.length;
167+
tabsCountP2 = Global.secondPaneWorkingSet.length;
167168
}
168169

169170
// get the active editor and path once to reuse for both panes
170171
const activeEditor = EditorManager.getActiveEditor();
171172
const activePath = activeEditor ? activeEditor.document.file.fullPath : null;
172173

173174
// handle the first pane tabs
174-
if (firstPaneWorkingSet.length > 0 && tabsCountP1 > 0 && $firstTabBar.length) {
175+
if (Global.firstPaneWorkingSet.length > 0 && tabsCountP1 > 0 && $firstTabBar.length) {
175176
// get the top n entries for the first pane
176-
let displayedEntries = firstPaneWorkingSet.slice(0, tabsCountP1);
177+
let displayedEntries = Global.firstPaneWorkingSet.slice(0, tabsCountP1);
177178

178179
// if the active file isn't already visible but exists in the working set, force-include it
179180
if (activePath && !displayedEntries.some(entry => entry.path === activePath)) {
180-
let activeEntry = firstPaneWorkingSet.find(entry => entry.path === activePath);
181+
let activeEntry = Global.firstPaneWorkingSet.find(entry => entry.path === activePath);
181182
if (activeEntry) {
182183
// replace the last tab with the active file.
183184
displayedEntries[displayedEntries.length - 1] = activeEntry;
@@ -191,11 +192,11 @@ define(function (require, exports, module) {
191192
}
192193

193194
// for second pane tabs
194-
if (secondPaneWorkingSet.length > 0 && tabsCountP2 > 0 && $secondTabBar.length) {
195-
let displayedEntries2 = secondPaneWorkingSet.slice(0, tabsCountP2);
195+
if (Global.secondPaneWorkingSet.length > 0 && tabsCountP2 > 0 && $secondTabBar.length) {
196+
let displayedEntries2 = Global.secondPaneWorkingSet.slice(0, tabsCountP2);
196197

197198
if (activePath && !displayedEntries2.some(entry => entry.path === activePath)) {
198-
let activeEntry = secondPaneWorkingSet.find(entry => entry.path === activePath);
199+
let activeEntry = Global.secondPaneWorkingSet.find(entry => entry.path === activePath);
199200
if (activeEntry) {
200201
displayedEntries2[displayedEntries2.length - 1] = activeEntry;
201202
}
@@ -368,8 +369,33 @@ define(function (require, exports, module) {
368369
// file dirty flag change handler
369370
DocumentManager.on("dirtyFlagChange", function (event, doc) {
370371
const filePath = doc.file.fullPath;
372+
373+
// Update UI
371374
const $tab = $tabBar.find(`.tab[data-path="${filePath}"]`);
372375
$tab.toggleClass('dirty', doc.isDirty);
376+
377+
// Also update the $tab2 if it exists
378+
if ($tabBar2) {
379+
const $tab2 = $tabBar2.find(`.tab[data-path="${filePath}"]`);
380+
$tab2.toggleClass('dirty', doc.isDirty);
381+
}
382+
383+
// Update the working set data
384+
// First pane
385+
for (let i = 0; i < Global.firstPaneWorkingSet.length; i++) {
386+
if (Global.firstPaneWorkingSet[i].path === filePath) {
387+
Global.firstPaneWorkingSet[i].isDirty = doc.isDirty;
388+
break;
389+
}
390+
}
391+
392+
// Second pane
393+
for (let i = 0; i < Global.secondPaneWorkingSet.length; i++) {
394+
if (Global.secondPaneWorkingSet[i].path === filePath) {
395+
Global.secondPaneWorkingSet[i].isDirty = doc.isDirty;
396+
break;
397+
}
398+
}
373399
});
374400

375401
// handle click events on the tab bar more options button

src/extensionsIntegrated/TabBar/more-options.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@ define(function (require, exports, module) {
1111
const CommandManager = require("command/CommandManager");
1212
const Commands = require("command/Commands");
1313

14+
const Global = require("./global");
15+
const Helper = require("./helper");
16+
1417
// List of items to show in the context menu
1518
// Strings defined in `src/nls/root/strings.js`
1619
const items = [
1720
Strings.CLOSE_ALL_TABS,
18-
Strings.CLOSE_UNMODIFIED_TABS
21+
Strings.CLOSE_UNMODIFIED_TABS,
22+
Strings.REOPEN_CLOSED_FILE
1923
];
2024

2125

@@ -27,6 +31,24 @@ define(function (require, exports, module) {
2731
CommandManager.execute(Commands.FILE_CLOSE_ALL);
2832
}
2933

34+
/**
35+
* Called when the close unmodified tabs option is selected from the context menu
36+
* This will close all tabs that are not modified
37+
* TODO: implement the functionality
38+
*/
39+
function handleCloseUnmodifiedTabs() {
40+
41+
// pass
42+
}
43+
44+
/**
45+
* Called when the reopen closed file option is selected from the context menu
46+
* This just calls the reopen closed file command. everthing else is handled there
47+
*/
48+
function reopenClosedFile() {
49+
CommandManager.execute(Commands.FILE_REOPEN_CLOSED);
50+
}
51+
3052

3153
/**
3254
* This function is called when the more options button is clicked
@@ -49,7 +71,11 @@ define(function (require, exports, module) {
4971
// handle the option selection
5072
dropdown.on("select", function (e, item, index) {
5173
if (index === 0) {
52-
handleCloseAllTabs(paneId);
74+
handleCloseAllTabs();
75+
} else if(index === 1) {
76+
handleCloseUnmodifiedTabs();
77+
} else if(index === 2) {
78+
reopenClosedFile();
5379
}
5480
});
5581

src/nls/root/strings.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ define({
429429
// Tab bar Strings
430430
"CLOSE_ALL_TABS": "Close All Tabs",
431431
"CLOSE_UNMODIFIED_TABS": "Close Unmodified Tabs",
432+
"REOPEN_CLOSED_FILE": "Reopen Closed File",
432433

433434
// CodeInspection: errors/warnings
434435
"ERRORS_NO_FILE": "No File Open",

0 commit comments

Comments
 (0)