mirror of https://github.com/atom/atom.git
147 lines
4.5 KiB
JavaScript
147 lines
4.5 KiB
JavaScript
const {CompositeDisposable} = require('event-kit')
|
|
const path = require('path')
|
|
|
|
module.exports =
|
|
class ReopenProjectMenuManager {
|
|
constructor ({menu, commands, history, config, open}) {
|
|
this.menuManager = menu
|
|
this.historyManager = history
|
|
this.config = config
|
|
this.open = open
|
|
this.projects = []
|
|
|
|
this.subscriptions = new CompositeDisposable()
|
|
this.subscriptions.add(
|
|
history.onDidChangeProjects(this.update.bind(this)),
|
|
config.onDidChange('core.reopenProjectMenuCount', ({oldValue, newValue}) => {
|
|
this.update()
|
|
}),
|
|
commands.add('atom-workspace', { 'application:reopen-project': this.reopenProjectCommand.bind(this) })
|
|
)
|
|
|
|
this.applyWindowsJumpListRemovals()
|
|
}
|
|
|
|
reopenProjectCommand (e) {
|
|
if (e.detail != null && e.detail.index != null) {
|
|
this.open(this.projects[e.detail.index].paths)
|
|
} else {
|
|
this.createReopenProjectListView()
|
|
}
|
|
}
|
|
|
|
createReopenProjectListView () {
|
|
if (this.reopenProjectListView == null) {
|
|
const ReopenProjectListView = require('./reopen-project-list-view')
|
|
this.reopenProjectListView = new ReopenProjectListView(paths => {
|
|
if (paths != null) {
|
|
this.open(paths)
|
|
}
|
|
})
|
|
}
|
|
this.reopenProjectListView.toggle()
|
|
}
|
|
|
|
update () {
|
|
this.disposeProjectMenu()
|
|
this.projects = this.historyManager.getProjects().slice(0, this.config.get('core.reopenProjectMenuCount'))
|
|
const newMenu = ReopenProjectMenuManager.createProjectsMenu(this.projects)
|
|
this.lastProjectMenu = this.menuManager.add([newMenu])
|
|
this.updateWindowsJumpList()
|
|
}
|
|
|
|
static taskDescription (paths) {
|
|
return paths.map(path => `${ReopenProjectMenuManager.betterBaseName(path)} (${path})`).join(' ')
|
|
}
|
|
|
|
// Windows users can right-click Atom taskbar and remove project from the jump list.
|
|
// We have to honor that or the group stops working. As we only get a partial list
|
|
// each time we remove them from history entirely.
|
|
async applyWindowsJumpListRemovals () {
|
|
if (process.platform !== 'win32') return
|
|
if (this.app === undefined) {
|
|
this.app = require('remote').app
|
|
}
|
|
|
|
const removed = this.app.getJumpListSettings().removedItems.map(i => i.description)
|
|
if (removed.length === 0) return
|
|
for (let project of this.historyManager.getProjects()) {
|
|
if (removed.includes(ReopenProjectMenuManager.taskDescription(project.paths))) {
|
|
await this.historyManager.removeProject(project.paths)
|
|
}
|
|
}
|
|
}
|
|
|
|
updateWindowsJumpList () {
|
|
if (process.platform !== 'win32') return
|
|
if (this.app === undefined) {
|
|
this.app = require('remote').app
|
|
}
|
|
|
|
this.app.setJumpList([
|
|
{
|
|
type: 'custom',
|
|
name: 'Recent Projects',
|
|
items: this.projects.map(project =>
|
|
({
|
|
type: 'task',
|
|
title: project.paths.map(ReopenProjectMenuManager.betterBaseName).join(', '),
|
|
description: ReopenProjectMenuManager.taskDescription(project.paths),
|
|
program: process.execPath,
|
|
args: project.paths.map(path => `"${path}"`).join(' '),
|
|
iconPath: path.join(path.dirname(process.execPath), 'resources', 'cli', 'folder.ico'),
|
|
iconIndex: 0
|
|
})
|
|
)
|
|
},
|
|
{ type: 'recent' },
|
|
{ items: [
|
|
{type: 'task', title: 'New Window', program: process.execPath, args: '--new-window', description: 'Opens a new Atom window'}
|
|
]}
|
|
])
|
|
}
|
|
|
|
dispose () {
|
|
this.subscriptions.dispose()
|
|
this.disposeProjectMenu()
|
|
if (this.reopenProjectListView != null) {
|
|
this.reopenProjectListView.dispose()
|
|
}
|
|
}
|
|
|
|
disposeProjectMenu () {
|
|
if (this.lastProjectMenu) {
|
|
this.lastProjectMenu.dispose()
|
|
this.lastProjectMenu = null
|
|
}
|
|
}
|
|
|
|
static createProjectsMenu (projects) {
|
|
return {
|
|
label: 'File',
|
|
submenu: [
|
|
{
|
|
label: 'Reopen Project',
|
|
submenu: projects.map((project, index) => ({
|
|
label: this.createLabel(project),
|
|
command: 'application:reopen-project',
|
|
commandDetail: {index: index}
|
|
}))
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
static createLabel (project) {
|
|
return project.paths.length === 1
|
|
? project.paths[0]
|
|
: project.paths.map(this.betterBaseName).join(', ')
|
|
}
|
|
|
|
static betterBaseName (directory) {
|
|
// Handles Windows roots better than path.basename which returns '' for 'd:' and 'd:\'
|
|
const match = directory.match(/^([a-z]:)[\\]?$/i)
|
|
return match ? match[1] + '\\' : path.basename(directory)
|
|
}
|
|
}
|