Skip to content

Commit f5870ff

Browse files
committed
chore: simplilfy recent projects dropdown by using new popupmanager APIs
1 parent b2bd89e commit f5870ff

File tree

4 files changed

+38
-201
lines changed

4 files changed

+38
-201
lines changed

src/assets/new-project/code-editor.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ <h4 class="localize">{{APP_TITLE}}</h4>
7070
<div class="project-content-left">
7171
<div id="recentProjectsContainer" class="recent-project-card">
7272
<div class="recent-head">
73-
<h5 class="localize">{{CMD_TOGGLE_RECENT_PROJECTS}}</h5>
73+
<h5 class="localize">{{CMD_RECENT_PROJECTS}}</h5>
7474
</div>
7575
<ul id="recentProjectList" class="recent-project-list">
7676

src/extensionsIntegrated/RecentProjects/main.js

Lines changed: 20 additions & 197 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ define(function (require, exports, module) {
3131
Commands = require("command/Commands"),
3232
CommandManager = require("command/CommandManager"),
3333
Menus = require("command/Menus"),
34-
MainViewManager = require("view/MainViewManager"),
3534
FileSystem = require("filesystem/FileSystem"),
3635
AppInit = require("utils/AppInit"),
3736
KeyEvent = require("utils/KeyEvent"),
@@ -47,16 +46,11 @@ define(function (require, exports, module) {
4746
ExtensionInterface.registerExtensionInterface(RECENT_PROJECTS_INTERFACE, exports);
4847
const RECENT_PROJECT_STATE = "recentProjects";
4948

50-
/** @const {string} Recent Projects commands ID */
51-
let TOGGLE_DROPDOWN = "recentProjects.toggle";
52-
5349
/** @const {number} Maximum number of displayed recent projects */
5450
var MAX_PROJECTS = 20;
5551

5652
/** @type {$.Element} jQuery elements used for the dropdown menu */
57-
var $dropdownItem,
58-
$dropdown,
59-
$links;
53+
let $dropdown;
6054

6155
/**
6256
* Get the stored list of recent projects, fixing up paths as appropriate.
@@ -109,156 +103,28 @@ define(function (require, exports, module) {
109103
PreferencesManager.setViewState(RECENT_PROJECT_STATE, newProjects);
110104
}
111105

112-
/**
113-
* Selects the next or previous item in the list
114-
* @param {number} direction +1 for next, -1 for prev
115-
*/
116-
function selectNextItem(direction) {
117-
let $links = $dropdown.find("a:visible"),
118-
index = $dropdownItem ? $links.index($dropdownItem) : (direction > 0 ? -1 : 0),
119-
$newItem = $links.eq((index + direction) % $links.length);
120-
121-
if(searchStr && $links.length === 1){
122-
// no search result, only the top search field visible
123-
return;
124-
}
125-
if($newItem.parent().hasClass("sticky-li-top")) {
126-
if(index === -1){
127-
index = 0;
128-
}
129-
$newItem = $links.eq((index + direction) % $links.length);
130-
}
131-
if ($dropdownItem) {
132-
$dropdownItem.removeClass("selected");
133-
}
134-
$newItem.addClass("selected");
135-
136-
$dropdownItem = $newItem;
137-
}
138-
139-
let searchStr ="";
140-
/**
141-
* hides all elements in popup that doesn't match the given search string, also shows the search bar in popup
142-
* @param searchString
143-
*/
144-
function filterDropdown(searchString) {
145-
searchStr = searchString;
146-
const $stickyLi = $dropdown.find('li.sticky-li-top');
147-
if(searchString){
148-
$stickyLi.removeClass("forced-hidden");
149-
} else {
150-
$stickyLi.addClass("forced-hidden");
151-
}
152-
153-
$dropdown.find('li').each(function(index, li) {
154-
if(index === 0){
155-
// this is the top search box itself
156-
return;
157-
}
158-
const $li = $(li);
159-
if(!$li.text().toLowerCase().includes(searchString.toLowerCase())){
160-
$li.addClass("forced-hidden");
161-
} else {
162-
$li.removeClass("forced-hidden");
163-
}
164-
});
165-
166-
if(searchString) {
167-
$stickyLi.removeClass('forced-hidden');
168-
$stickyLi.find('.searchTextSpan').text(searchString);
169-
} else {
170-
$stickyLi.addClass('forced-hidden');
171-
}
172-
}
173-
174-
/**
175-
* Deletes the selected item and
176-
* move the focus to next item in list.
177-
*
178-
* @return {boolean} TRUE if project is removed
179-
*/
180-
function removeSelectedItem(e) {
181-
var recentProjects = getRecentProjects(),
182-
$cacheItem = $dropdownItem,
183-
index = recentProjects.indexOf($cacheItem.data("path"));
184-
185-
// When focus is not on project item
186-
if (index === -1) {
187-
return false;
188-
}
189-
190-
// remove project
191-
recentProjects.splice(index, 1);
192-
PreferencesManager.setViewState(RECENT_PROJECT_STATE, recentProjects);
193-
194-
if (recentProjects.length === 1) {
195-
$dropdown.find(".divider").remove();
196-
}
197-
selectNextItem(+1);
198-
$cacheItem.closest("li").remove();
199-
return true;
200-
}
201-
202106
/**
203107
* Handles the Key Down events
204108
* @param {KeyboardEvent} event
109+
* @param $popUp
205110
* @return {boolean} True if the key was handled
206111
*/
207-
function keydownHook(event) {
208-
var keyHandled = false;
209-
210-
switch (event.keyCode) {
211-
case KeyEvent.DOM_VK_UP:
212-
selectNextItem(-1);
213-
keyHandled = true;
214-
break;
215-
case KeyEvent.DOM_VK_DOWN:
216-
selectNextItem(+1);
217-
keyHandled = true;
218-
break;
219-
case KeyEvent.DOM_VK_ENTER:
220-
case KeyEvent.DOM_VK_RETURN:
221-
if ($dropdownItem) {
222-
$dropdownItem.trigger("click");
223-
}
224-
keyHandled = true;
225-
break;
226-
case KeyEvent.DOM_VK_DELETE:
227-
if ($dropdownItem) {
228-
removeSelectedItem(event);
229-
}
230-
keyHandled = true;
231-
break;
232-
}
233-
234-
if(keyHandled){
235-
event.stopImmediatePropagation();
236-
event.preventDefault();
237-
return keyHandled;
238-
} else if((event.ctrlKey || event.metaKey) && event.key === 'v') {
239-
Phoenix.app.clipboardReadText().then(text=>{
240-
searchStr += text;
241-
filterDropdown(searchStr);
242-
});
243-
keyHandled = true;
244-
} else if (event.key.length === 1) {
245-
searchStr += event.key;
246-
keyHandled = true;
247-
} else if (event.key === 'Backspace') {
248-
// Remove the last character when Backspace is pressed
249-
searchStr = searchStr.slice(0, -1);
250-
keyHandled = true;
251-
} else {
252-
// bubble up, not for us to handle
253-
return false;
254-
}
255-
filterDropdown(searchStr);
112+
function _handlePopupKeyEvents(event, $popUp) {
113+
if(event.keyCode === KeyEvent.DOM_VK_DELETE){
114+
event.stopPropagation();
115+
const $selectedItem = $popUp.find(".selected");
116+
if ($selectedItem.length && $selectedItem.data("path")) {
117+
// Remove the project from the preferences.
118+
removeFromRecentProject($selectedItem.data("path"));
119+
PopUpManager.selectNextItem(+1, $popUp);
120+
$selectedItem.closest("li").remove();
256121

257-
if (keyHandled) {
258-
event.stopImmediatePropagation();
259-
event.preventDefault();
122+
if (getRecentProjects().length === 1) {
123+
$dropdown.find(".divider").remove();
124+
}
125+
}
126+
return true;
260127
}
261-
return keyHandled;
262128
}
263129

264130

@@ -272,7 +138,6 @@ define(function (require, exports, module) {
272138
if ($dropdown) {
273139
PopUpManager.removePopUp($dropdown);
274140
}
275-
searchStr = "";
276141
}
277142

278143
/**
@@ -284,9 +149,6 @@ define(function (require, exports, module) {
284149
$("#project-files-container").off("scroll", closeDropdown);
285150
$("#titlebar .nav").off("click", closeDropdown);
286151
$dropdown = null;
287-
288-
$(window).off("keydown", keydownHook);
289-
searchStr = "";
290152
}
291153

292154
function openProjectWithPath(fullPath) {
@@ -345,19 +207,6 @@ define(function (require, exports, module) {
345207
CommandManager.execute(Commands.FILE_DOWNLOAD_PROJECT);
346208
}
347209

348-
})
349-
.on("mouseenter", "a", function () {
350-
if ($dropdownItem) {
351-
$dropdownItem.removeClass("selected");
352-
}
353-
$dropdownItem = $(this).addClass("selected");
354-
})
355-
.on("mouseleave", "a", function () {
356-
var $link = $(this).removeClass("selected");
357-
358-
if ($link.get(0) === $dropdownItem.get(0)) {
359-
$dropdownItem = null;
360-
}
361210
});
362211
}
363212

@@ -428,6 +277,10 @@ define(function (require, exports, module) {
428277
.appendTo($("body"));
429278

430279
PopUpManager.addPopUp($dropdown, cleanupDropdown, true, {closeCurrentPopups: true});
280+
PopUpManager.handleSelectionEvents($dropdown, {
281+
enableSearchFilter: true,
282+
keyboardEventHandler: _handlePopupKeyEvents
283+
});
431284

432285
// TODO: should use capture, otherwise clicking on the menus doesn't close it. More fallout
433286
// from the fact that we can't use the Boostrap (1.4) dropdowns.
@@ -448,38 +301,8 @@ define(function (require, exports, module) {
448301
$("#titlebar .nav").on("click", closeDropdown);
449302

450303
_handleListEvents();
451-
$(window).on("keydown", keydownHook);
452-
}
453-
454-
455-
/**
456-
* Show or hide the recent projects dropdown from the toogle command.
457-
*/
458-
function handleKeyEvent() {
459-
if (!$dropdown) {
460-
if (!SidebarView.isVisible()) {
461-
SidebarView.show();
462-
}
463-
464-
$("#project-dropdown-toggle").trigger("click");
465-
466-
$dropdown.focus();
467-
$links = $dropdown.find("a");
468-
// By default, select the most recent project (which is at the top of the list underneath Open Folder),
469-
// but if there are none, select Open Folder instead.
470-
$dropdownItem = $links.eq($links.length > 1 ? 1 : 0);
471-
$dropdownItem.addClass("selected");
472-
473-
// If focusing the dropdown caused a modal bar to close, we need to refocus the dropdown
474-
window.setTimeout(function () {
475-
$dropdown.focus();
476-
}, 0);
477-
}
478304
}
479305

480-
// Register command handlers
481-
CommandManager.register(Strings.CMD_TOGGLE_RECENT_PROJECTS, TOGGLE_DROPDOWN, handleKeyEvent);
482-
483306
// Initialize extension
484307
AppInit.appReady(function () {
485308
PreferencesManager.stateManager.definePreference(RECENT_PROJECT_STATE, 'array', [])

src/nls/root/strings.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,7 @@ define({
954954
"TOOLTIP_CLICK_TO_EDIT_COLOR": "Click here to edit color",
955955

956956
// extensions/default/RecentProjects
957-
"CMD_TOGGLE_RECENT_PROJECTS": "Recent Projects",
957+
"CMD_RECENT_PROJECTS": "Recent Projects",
958958
"REMOVE_FROM_RECENT_PROJECTS": "Remove from Recent Projects",
959959

960960
// extensions/default/MDNDocs

src/widgets/PopUpManager.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,19 @@ define(function (require, exports, module) {
8888
$popUp.off("keydown", _processSelectionEvent);
8989
$popUp.on("keydown", _processSelectionEvent);
9090
$popUp.focus();
91+
function _selectItem() {
92+
$popUp.find(".selected").removeClass("selected");
93+
$(this).addClass("selected");
94+
}
95+
function _unselectItem() {
96+
$(this).removeClass("selected");
97+
}
98+
$popUp
99+
.off("mouseenter", "a", _selectItem)
100+
.off("mouseleave", "a", _unselectItem);
101+
$popUp
102+
.on("mouseenter", "a", _selectItem)
103+
.on("mouseleave", "a", _unselectItem);
91104
}
92105

93106
/**
@@ -207,7 +220,7 @@ define(function (require, exports, module) {
207220

208221

209222
/**
210-
* Selects the next or previous item in the list
223+
* Selects the next or previous item in the popup.
211224
* @param {number} direction +1 for next, -1 for prev
212225
* @param $popUp
213226
*/
@@ -246,7 +259,7 @@ define(function (require, exports, module) {
246259
return false;
247260
}
248261
if(keyboardEventHandler) {
249-
const processed = keyboardEventHandler(event);
262+
const processed = keyboardEventHandler(event, $popUp);
250263
if(processed){
251264
return true;
252265
}
@@ -367,6 +380,7 @@ define(function (require, exports, module) {
367380

368381
exports.addPopUp = addPopUp;
369382
exports.handleSelectionEvents = handleSelectionEvents;
383+
exports.selectNextItem = selectNextItem;
370384
exports.removePopUp = removePopUp;
371385
exports.closeAllPopups = closeAllPopups;
372386
exports.listenToContextMenu = listenToContextMenu;

0 commit comments

Comments
 (0)