diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index 003d208ae..bb8c42d12 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -2,7 +2,7 @@ fs = require 'fs' path = require 'path' os = require 'os' -# This is the main Gruntfile that manages building Edgehill distributions. +# This is the main Gruntfile that manages building Nylas Mail distributions. # The reason it's inisde of the build/ folder is so everything can be # compiled against Node's v8 headers instead of Atom's v8 headers. All # packages in the root-level node_modules are compiled against Atom's v8 @@ -17,25 +17,25 @@ os = require 'os' # # tmpDir: /var/folders/xl/_qdlmc512sb6cpqryy_2tzzw0000gn/T/ (aka /tmp) # -# buildDir = /tmp/edgehill-build -# shellAppDir = /tmp/edgehill-build/Edgehill.app -# contentsDir = /tmp/edgehill-build/Edgehill.app/Contents -# appDir = /tmp/edgehill-build/Edgehill.app/Contents/Resources/app +# buildDir = /tmp/nylas-build +# shellAppDir = /tmp/nylas-build/Nylas.app +# contentsDir = /tmp/nylas-build/Nylas.app/Contents +# appDir = /tmp/nylas-build/Nylas.app/Contents/Resources/app # -# installDir = /Applications/Edgehil.app +# installDir = /Applications/Nylas.app # # And on Linux: # # tmpDir: /tmp/ # -# buildDir = /tmp/edgehill-build -# shellAppDir = /tmp/edgehill-build/Edgehill -# contentsDir = /tmp/edgehill-build/Edgehill -# appDir = /tmp/edgehill-build/Edgehill/resources/app +# buildDir = /tmp/nylas-build +# shellAppDir = /tmp/nylas-build/Nylas +# contentsDir = /tmp/nylas-build/Nylas +# appDir = /tmp/nylas-build/Nylas/resources/app # # installDir = /usr/local OR $INSTALL_PREFIX # binDir = /usr/local/bin -# shareDir = /usr/local/share/edgehill +# shareDir = /usr/local/share/nylas # Add support for obselete APIs of vm module so we can make some third-party # modules work under node v0.11.x. @@ -99,7 +99,7 @@ module.exports = (grunt) -> contentsDir = shellAppDir appDir = path.join(shellAppDir, 'resources', 'app') installDir ?= process.env.INSTALL_PREFIX ? '/usr/local' - killCommand ='pkill -9 nylas' + killCommand = 'pkill -9 nylas' installDir = path.resolve(installDir) @@ -166,18 +166,19 @@ module.exports = (grunt) -> dest: appDir ext: '.js' - for child in fs.readdirSync('node_modules') when child isnt '.bin' - directory = path.join('node_modules', child) - metadataPath = path.join(directory, 'package.json') - continue unless grunt.file.isFile(metadataPath) + for folder in ['node_modules', 'internal_packages'] + for child in fs.readdirSync(folder) when child isnt '.bin' + directory = path.join(folder, child) + metadataPath = path.join(directory, 'package.json') + continue unless grunt.file.isFile(metadataPath) - {engines, theme} = grunt.file.readJSON(metadataPath) - if engines?.atom? - coffeeConfig.glob_to_multiple.src.push("#{directory}/**/*.coffee") - lessConfig.glob_to_multiple.src.push("#{directory}/**/*.less") - prebuildLessConfig.src.push("#{directory}/**/*.less") unless theme - csonConfig.glob_to_multiple.src.push("#{directory}/**/*.cson") - pegConfig.glob_to_multiple.src.push("#{directory}/**/*.pegjs") + {engines, theme} = grunt.file.readJSON(metadataPath) + if engines?.atom? + coffeeConfig.glob_to_multiple.src.push("#{directory}/**/*.coffee") + lessConfig.glob_to_multiple.src.push("#{directory}/**/*.less") + prebuildLessConfig.src.push("#{directory}/**/*.less") unless theme + csonConfig.glob_to_multiple.src.push("#{directory}/**/*.cson") + pegConfig.glob_to_multiple.src.push("#{directory}/**/*.pegjs") grunt.initConfig pkg: grunt.file.readJSON('package.json') @@ -304,16 +305,16 @@ module.exports = (grunt) -> ciTasks = ['output-disk-space', 'download-electron', 'build'] ciTasks.push('dump-symbols') if process.platform isnt 'win32' - ciTasks.push('set-version', 'lint') + ciTasks.push('set-version', 'lint', 'generate-asar') ciTasks.push('mkdeb') if process.platform is 'linux' ciTasks.push('test') if process.platform is 'darwin' ciTasks.push('codesign') ciTasks.push('mkdmg') if process.platform is 'darwin' ciTasks.push('create-windows-installer') if process.platform is 'win32' - ciTasks.push('publish-edgehill-build') if process.platform is 'darwin' + ciTasks.push('publish-nylas-build') if process.platform is 'darwin' grunt.registerTask('ci', ciTasks) - defaultTasks = ['download-electron', 'build', 'set-version'] + defaultTasks = ['download-electron', 'build', 'set-version', 'generate-asar'] # We don't run `install` on linux because you need to run `sudo`. # See docs/build-instructions/linux.md # `sudo script/grunt install` diff --git a/build/package.json b/build/package.json index 5ff8b9f9a..b12d785a1 100644 --- a/build/package.json +++ b/build/package.json @@ -1,5 +1,5 @@ { - "name": "edgehill-build", + "name": "nylas-build", "description": "Nylas Mail build", "repository": { "type": "git", diff --git a/build/tasks/build-task.coffee b/build/tasks/build-task.coffee index 458d3814b..84f5b67d7 100644 --- a/build/tasks/build-task.coffee +++ b/build/tasks/build-task.coffee @@ -110,8 +110,6 @@ module.exports = (grunt) -> '.gitkeep' ] - packageNames.forEach (packageName) -> ignoredPaths.push(path.join(packageName, 'spec')) - ignoredPaths = ignoredPaths.map (ignoredPath) -> escapeRegExp(ignoredPath) # Add .* to avoid matching hunspell_dictionaries. @@ -141,19 +139,14 @@ module.exports = (grunt) -> testFolderPattern = new RegExp("#{escapeRegExp(path.sep)}te?sts?#{escapeRegExp(path.sep)}") exampleFolderPattern = new RegExp("#{escapeRegExp(path.sep)}examples?#{escapeRegExp(path.sep)}") - benchmarkFolderPattern = new RegExp("#{escapeRegExp(path.sep)}benchmarks?#{escapeRegExp(path.sep)}") nodeModulesFilter = new RegExp(ignoredPaths.join('|')) filterNodeModule = (pathToCopy) -> - return true if benchmarkFolderPattern.test(pathToCopy) - pathToCopy = path.resolve(pathToCopy) nodeModulesFilter.test(pathToCopy) or testFolderPattern.test(pathToCopy) or exampleFolderPattern.test(pathToCopy) packageFilter = new RegExp("(#{ignoredPaths.join('|')})|(.+\\.(cson|coffee|cjsx|jsx)$)") filterPackage = (pathToCopy) -> - return true if benchmarkFolderPattern.test(pathToCopy) - pathToCopy = path.resolve(pathToCopy) packageFilter.test(pathToCopy) or testFolderPattern.test(pathToCopy) or exampleFolderPattern.test(pathToCopy) diff --git a/build/tasks/compile-packages-slug-task.coffee b/build/tasks/compile-packages-slug-task.coffee index 9e92fc004..bab2940d4 100644 --- a/build/tasks/compile-packages-slug-task.coffee +++ b/build/tasks/compile-packages-slug-task.coffee @@ -43,12 +43,10 @@ module.exports = (grunt) -> for keymapPath in fs.listSync(path.join(moduleDirectory, 'keymaps'), ['.cson', '.json']) relativePath = path.relative(appDir, keymapPath) pack.keymaps[relativePath] = CSON.readFileSync(keymapPath) - rm keymapPath for menuPath in fs.listSync(path.join(moduleDirectory, 'menus'), ['.cson', '.json']) relativePath = path.relative(appDir, menuPath) pack.menus[relativePath] = CSON.readFileSync(menuPath) - rm menuPath packages[metadata.name] = pack diff --git a/build/tasks/generate-asar-task.coffee b/build/tasks/generate-asar-task.coffee new file mode 100644 index 000000000..47ad475f8 --- /dev/null +++ b/build/tasks/generate-asar-task.coffee @@ -0,0 +1,31 @@ +asar = require 'asar' +fs = require 'fs' +path = require 'path' + +module.exports = (grunt) -> + {cp, rm} = require('./task-helpers')(grunt) + + grunt.registerTask 'generate-asar', 'Generate asar archive for the app', -> + done = @async() + + unpack = [ + '*.node' + '**/vendor/**' + '**/src/tasks/**' + '**/node_modules/aws-sdk/**' + '**/node_modules/spellchecker/**' + ] + unpack = "{#{unpack.join(',')}}" + + appDir = grunt.config.get('atom.appDir') + unless fs.existsSync(appDir) + grunt.log.error 'The app has to be built before generating asar archive.' + return done(false) + + asar.createPackageWithOptions appDir, path.resolve(appDir, '..', 'app.asar'), {unpack}, (err) -> + return done(err) if err? + + rm appDir + fs.renameSync path.resolve(appDir, '..', 'new-app'), appDir + + done() diff --git a/build/tasks/publish-edgehill-build-task.coffee b/build/tasks/publish-nylas-build-task.coffee similarity index 98% rename from build/tasks/publish-edgehill-build-task.coffee rename to build/tasks/publish-nylas-build-task.coffee index 524a5b7c3..b71ec28aa 100644 --- a/build/tasks/publish-edgehill-build-task.coffee +++ b/build/tasks/publish-nylas-build-task.coffee @@ -123,7 +123,7 @@ module.exports = (grunt) -> process.chdir(orig) reject(err) - grunt.registerTask "publish-edgehill-build", "Publish Edgehill build", -> + grunt.registerTask "publish-nylas-build", "Publish Nylas build", -> done = @async() dmgPath = path.join(grunt.config.get('atom.buildDir'), dmgName()) diff --git a/docs-atom/build-instructions/freebsd.md b/docs-atom/build-instructions/freebsd.md index afd56e546..14f7fc4d5 100644 --- a/docs-atom/build-instructions/freebsd.md +++ b/docs-atom/build-instructions/freebsd.md @@ -15,8 +15,8 @@ FreeBSD -RELEASE 64-bit is the recommended platform. ```sh git clone https://github.com/nylas/edgehill cd edgehill - script/build # Creates application at $TMPDIR/edgehill-build/Edgehill - sudo script/grunt install # Installs command to /usr/local/bin/edgehill + script/build # Creates application at $TMPDIR/nylas-build/Nylas + sudo script/grunt install # Installs command to /usr/local/bin/nylas ``` ## Troubleshooting diff --git a/docs-atom/build-instructions/linux.md b/docs-atom/build-instructions/linux.md index 7176b2d78..254632672 100644 --- a/docs-atom/build-instructions/linux.md +++ b/docs-atom/build-instructions/linux.md @@ -61,7 +61,7 @@ If you have problems with permissions don't forget to prefix with `sudo` script/build ``` - This will create the Nylas Mail application at `$TMPDIR/edgehill-build/Edgehill`. + This will create the Nylas Mail application at `$TMPDIR/nylas-build/Nylas`. 4. Install the `edgehill` and `apm` commands to `/usr/local/bin` by executing: @@ -71,7 +71,7 @@ If you have problems with permissions don't forget to prefix with `sudo` To use the newly installed Nylas Mail, quit and restart all running Nylas Mail instances. -5. *Optionally*, you may generate distributable packages of Nylas Mail at `$TMPDIR/edgehill-build`. Currenty, `.deb` and `.rpm` package types are supported. To create a `.deb` package run: +5. *Optionally*, you may generate distributable packages of Nylas Mail at `$TMPDIR/nylas-build`. Currenty, `.deb` and `.rpm` package types are supported. To create a `.deb` package run: ```sh script/grunt mkdeb diff --git a/internal_packages/composer/spec/inbox-composer-view-spec.cjsx b/internal_packages/composer/spec/inbox-composer-view-spec.cjsx index 5148f4dcb..1901c1436 100644 --- a/internal_packages/composer/spec/inbox-composer-view-spec.cjsx +++ b/internal_packages/composer/spec/inbox-composer-view-spec.cjsx @@ -335,7 +335,7 @@ describe "populated composer", -> useFullDraft.apply(@) makeComposer.call(@) spyOn(@composer, "_sendDraft") - NylasTestUtils.loadKeymap "internal_packages/composer/keymaps/composer.cson" + NylasTestUtils.loadKeymap("internal_packages/composer/keymaps/composer") it "sends the draft on cmd-enter", -> NylasTestUtils.keyPress("cmd-enter", React.findDOMNode(@composer)) diff --git a/internal_packages/developer-bar/lib/developer-bar.cjsx b/internal_packages/developer-bar/lib/developer-bar.cjsx index 5214382ab..45f31f2aa 100644 --- a/internal_packages/developer-bar/lib/developer-bar.cjsx +++ b/internal_packages/developer-bar/lib/developer-bar.cjsx @@ -35,7 +35,10 @@ class DeveloperBar extends React.Component @activityStoreUnsubscribe() if @activityStoreUnsubscribe render: => - return
unless @state.visible + # TODO WARNING: This 1px height is necessary to fix a redraw issue in the thread + # list in Chrome 42 (Electron 0.26.0). Do not remove unless you've verified that + # scrolling works fine now and repaints aren't visible. + return
unless @state.visible beforeEach -> diff --git a/internal_packages/thread-list/spec/thread-list-spec.cjsx b/internal_packages/thread-list/spec/thread-list-spec.cjsx index dd9ef5abb..09b0ef1a8 100644 --- a/internal_packages/thread-list/spec/thread-list-spec.cjsx +++ b/internal_packages/thread-list/spec/thread-list-spec.cjsx @@ -219,7 +219,7 @@ describe "ThreadList", -> columns = [c1,c2,c3] beforeEach -> - NylasTestUtils.loadKeymap("internal_packages/thread-list/keymaps/thread-list.cson") + NylasTestUtils.loadKeymap("internal_packages/thread-list/keymaps/thread-list") spyOn(ThreadStore, "_onNamespaceChanged") spyOn(DatabaseStore, "findAll").andCallFake -> new Promise (resolve, reject) -> resolve(test_threads()) diff --git a/menus/darwin.cson b/menus/darwin.cson index 046b11a0d..5a39bf237 100644 --- a/menus/darwin.cson +++ b/menus/darwin.cson @@ -54,6 +54,9 @@ submenu: [ { label: 'Open In Dev Mode...', command: 'application:open-dev' } { type: 'separator' } + { label: 'Open Detailed Logs', command: 'window:open-errorreporter-logs' } + { label: 'Ship Detailed Logs to Nylas', command: 'application:ship-logs' } + { type: 'separator' } { label: 'Run Nylas Mail Specs', command: 'application:run-all-specs' } { label: 'Run Package Specs', command: 'application:run-package-specs' } { label: 'Toggle Developer Tools', command: 'window:toggle-dev-tools' } diff --git a/menus/linux.cson b/menus/linux.cson index 91755c224..7516510d4 100644 --- a/menus/linux.cson +++ b/menus/linux.cson @@ -37,6 +37,9 @@ submenu: [ { label: 'Open In &Dev Mode...', command: 'application:open-dev' } { type: 'separator' } + { label: 'Open Detailed Logs', command: 'window:open-errorreporter-logs' } + { label: 'Ship Detailed Logs to Nylas', command: 'application:ship-logs' } + { type: 'separator' } { label: 'Run &Nylas Mail Specs', command: 'application:run-all-specs' } { label: 'Run Package &Specs', command: 'application:run-package-specs' } { label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' } diff --git a/menus/win32.cson b/menus/win32.cson index eb82a71c3..e01f0e5dc 100644 --- a/menus/win32.cson +++ b/menus/win32.cson @@ -39,6 +39,9 @@ submenu: [ { label: 'Open In &Dev Mode...', command: 'application:open-dev' } { type: 'separator' } + { label: 'Open Detailed Logs', command: 'window:open-errorreporter-logs' } + { label: 'Ship Detailed Logs to Nylas', command: 'application:ship-logs' } + { type: 'separator' } { label: 'Run &Atom Specs', command: 'application:run-all-specs' } { label: 'Run Package &Specs', command: 'application:run-package-specs' } { label: 'Toggle Developer &Tools', command: 'window:toggle-dev-tools' } diff --git a/resources/linux/nylas.desktop.in b/resources/linux/nylas.desktop.in index 4f700120b..5c63e5038 100644 --- a/resources/linux/nylas.desktop.in +++ b/resources/linux/nylas.desktop.in @@ -1,8 +1,8 @@ [Desktop Entry] -Name=Edgehill +Name=Nylas Comment=<%= description %> -GenericName=Email OS -Exec=<%= installDir %>/share/edgehill/edgehill %U +GenericName=Nylas +Exec=<%= installDir %>/share/nylas/nylas %U Icon=<%= iconName %> Type=Application StartupNotify=true diff --git a/spec-nylas/components/form-builder-spec.cjsx b/spec-nylas/components/form-builder-spec.cjsx index fe9f3d9f2..49eaf3f93 100644 --- a/spec-nylas/components/form-builder-spec.cjsx +++ b/spec-nylas/components/form-builder-spec.cjsx @@ -6,8 +6,8 @@ ReactTestUtils = React.addons.TestUtils GeneratedForm, GeneratedFieldset} = require ('../../src/components/generated-form') -fixtureModule = 'internal_packages/salesforce' -Adapter = require path.join('../../', fixtureModule, 'lib/salesforce-schema-adapter.coffee') +fixtureModule = path.resolve(__dirname, '..', '..', 'internal_packages', 'salesforce') +Adapter = require(path.join(fixtureModule, 'lib/salesforce-schema-adapter')) fpath = path.join(fixtureModule, 'spec/fixtures/opportunity-layouts.json') rawData = JSON.parse(fs.readFileSync(fpath, 'utf-8')) testData = Adapter.convertFullEditLayout("opportunity", rawData) diff --git a/spec-nylas/stores/task-queue-spec.coffee b/spec-nylas/stores/task-queue-spec.coffee index 235b09b0a..1489cd517 100644 --- a/spec-nylas/stores/task-queue-spec.coffee +++ b/spec-nylas/stores/task-queue-spec.coffee @@ -89,6 +89,27 @@ describe "TaskQueue", -> remoteSpy = (task) -> spyOn(task, "performRemote").andCallFake -> Promise.resolve() + describe "findTask", -> + beforeEach -> + @subclassA = new TaskSubclassA() + @subclassB1 = new TaskSubclassB("B1") + @subclassB2 = new TaskSubclassB("B2") + TaskQueue._queue = [@subclassA, @subclassB1, @subclassB2] + + it "accepts type as a string", -> + expect(TaskQueue.findTask('TaskSubclassB', {bProp: 'B1'})).toEqual(@subclassB1) + + it "accepts type as a class", -> + expect(TaskQueue.findTask(TaskSubclassB, {bProp: 'B1'})).toEqual(@subclassB1) + + it "works without a set of match criteria", -> + expect(TaskQueue.findTask(TaskSubclassA)).toEqual(@subclassA) + + it "only returns a task that matches the criteria", -> + expect(TaskQueue.findTask(TaskSubclassB, {bProp: 'B1'})).toEqual(@subclassB1) + expect(TaskQueue.findTask(TaskSubclassB, {bProp: 'B2'})).toEqual(@subclassB2) + expect(TaskQueue.findTask(TaskSubclassB, {bProp: 'B3'})).toEqual(null) + describe "enqueue", -> it "makes sure you've queued a real task", -> expect( -> TaskQueue.enqueue("asamw")).toThrow() diff --git a/spec-nylas/test_utils.coffee b/spec-nylas/test_utils.coffee index 1a72bee7f..77cd54abe 100644 --- a/spec-nylas/test_utils.coffee +++ b/spec-nylas/test_utils.coffee @@ -4,10 +4,13 @@ KeymapManager = require 'atom-keymap' NylasTestUtils = loadKeymap: (keymapPath) -> - baseKeymaps = CSON.readFileSync("keymaps/base.cson") - atom.keymaps.add("keymaps/base.cson", baseKeymaps) + {resourcePath} = atom.getLoadSettings() + basePath = CSON.resolve("#{resourcePath}/keymaps/base") + baseKeymaps = CSON.readFileSync(basePath) + atom.keymaps.add(basePath, baseKeymaps) if keymapPath? + keymapPath = CSON.resolve("#{resourcePath}/#{keymapPath}") keymapFile = CSON.readFileSync(keymapPath) atom.keymaps.add(keymapPath, keymapFile) @@ -16,4 +19,3 @@ NylasTestUtils = document.dispatchEvent(event) module.exports = NylasTestUtils - diff --git a/spec/spec-bootstrap.coffee b/spec/spec-bootstrap.coffee index aad9ade49..75fd356b6 100644 --- a/spec/spec-bootstrap.coffee +++ b/spec/spec-bootstrap.coffee @@ -1,5 +1,6 @@ # Start the crash reporter before anything else. -require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub') +require('crash-reporter').start(productName: 'Nylas Mail', companyName: 'Nylas') + path = require 'path' fs = require 'fs-plus' diff --git a/src/browser/application.coffee b/src/browser/application.coffee index 8b4dc7067..6c6aced60 100644 --- a/src/browser/application.coffee +++ b/src/browser/application.coffee @@ -119,7 +119,7 @@ class Application # return a promise that resolves after we've configured dblite for our platform return @dblitePromise = new Promise (resolve, reject) => dblite = require('../../vendor/dblite-custom').withSQLite('3.8.6+') - vendor = @resourcePath + "/vendor" + vendor = path.join(@resourcePath.replace('app.asar', 'app.asar.unpacked'), '/vendor') if process.platform is 'win32' dblite.bin = "#{vendor}/sqlite3-win32.exe" @@ -192,9 +192,17 @@ class Application @on 'application:run-all-specs', -> @runSpecs exitWhenDone: false - resourcePath: global.devResourcePath + resourcePath: @resourcePath safeMode: @windowManager.focusedWindow()?.safeMode + @on 'application:ship-logs', -> + global.errorReporter.shipLogs("User triggered.") + dialog.showMessageBox + type: 'warning' + buttons: ['OK'] + message: 'Your local Nylas Mail logs have been sent to LogStash.' + title: 'Logs Shipped' + @on 'application:run-package-specs', -> dialog.showOpenDialog { title: 'Choose a Package Directory' @@ -204,7 +212,7 @@ class Application return if filenames.length is 0 @runSpecs exitWhenDone: false - resourcePath: global.devResourcePath + resourcePath: @resourcePath specDirectory: filenames[0] @on 'application:run-benchmarks', -> diff --git a/src/browser/main.js b/src/browser/main.js index 3cffe7c3c..2abb4d8f6 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -2,7 +2,7 @@ var app, errorReporter, fs, lstatSyncNoException, optimist, parseCommandLine, pa global.shellStartTime = Date.now(); -errorReporter = new (require('../error-reporter')); +global.errorReporter = new (require('../error-reporter')); app = require('app'); diff --git a/src/components/timeout-transition-group.cjsx b/src/components/timeout-transition-group.cjsx index 9d3431eb7..6b7887446 100644 --- a/src/components/timeout-transition-group.cjsx +++ b/src/components/timeout-transition-group.cjsx @@ -21,26 +21,14 @@ animationSupported = => true ### addClass = (element, className) => - if element.classList - element.classList.add className - else if !hasClass(element, className) - element.className = element.className + ' ' + className + element.classList.add(className) element removeClass = (element, className) => - if hasClass(className) - if element.classList - element.classList.remove className - else - element.className = (' ' + element.className + ' ').replace(' ' + className + ' ', ' ').trim() + if element.classList.contains(className) + element.classList.remove(className) element -hasClass = (element, className) => - if element.classList - element.classList.contains className - else - (' ' + element.className + ' ').indexOf(' ' + className + ' ') > -1 - ### Public: TimeoutTransitionGroup applies a CSS transition to the components added diff --git a/src/error-reporter.js b/src/error-reporter.js index 9060fdba8..11e08e624 100644 --- a/src/error-reporter.js +++ b/src/error-reporter.js @@ -14,7 +14,14 @@ if (process.type === 'renderer') { app = require('app'); } -tmpPath = app.getPath('temp'); +var tmpPath = app.getPath('temp'); + +var logpid = process.pid; +if (process.type === 'renderer') { + logpid = remote.process.pid + "." + process.pid; +} +var logpath = path.join(tmpPath, 'edgehill-' + logpid + '.log'); + module.exports = ErrorReporter = (function() { function ErrorReporter() { @@ -55,11 +62,6 @@ module.exports = ErrorReporter = (function() { } // Open a file write stream to log output from this process - var pid = process.pid; - if (process.type === 'renderer') { - pid = remote.process.pid + "." + process.pid; - } - var logpath = path.join(tmpPath, 'edgehill-' + pid + '.log'); console.log("Streaming log data to "+logpath); this.loghost = os.hostname(); @@ -162,6 +164,11 @@ module.exports = ErrorReporter = (function() { } }; + ErrorReporter.prototype.openLogs = function() { + var shell = require('shell'); + shell.openItem(logpath); + }; + ErrorReporter.prototype.shipLogs = function(reason) { if (!this.shipLogsQueued) { var timeSinceLogShip = Date.now() - this.shipLogsTime; diff --git a/src/flux/stores/draft-store.coffee b/src/flux/stores/draft-store.coffee index d67c93f79..23c54e41c 100644 --- a/src/flux/stores/draft-store.coffee +++ b/src/flux/stores/draft-store.coffee @@ -98,10 +98,7 @@ class DraftStore # In popout windows the existance of the window is the sending state. isSendingDraft: (draftLocalId) -> if atom.isMainWindow() - task = TaskQueue.findTask - object: "SendDraftTask" - matchKey: "draftLocalId" - matchValue: draftLocalId + task = TaskQueue.findTask(SendDraftTask, {draftLocalId}) return task? else return false @@ -376,11 +373,10 @@ class DraftStore # edits and are destroying the session. If there are errors down # the line, we'll make a new session and handle them later @_doneWithSession(session) + @trigger() atom.close() if @_isPopout() - @trigger() - _isPopout: -> atom.getWindowType() is "composer" diff --git a/src/flux/stores/file-upload-store.coffee b/src/flux/stores/file-upload-store.coffee index 8886fca2c..cf344c074 100644 --- a/src/flux/stores/file-upload-store.coffee +++ b/src/flux/stores/file-upload-store.coffee @@ -43,7 +43,7 @@ FileUploadStore = Reflux.createStore for path in pathsToOpen # When this task runs, we expect to hear `uploadStateChanged` actions. Actions.attachFilePath({messageLocalId, path}) - + _onAttachFilePath: ({messageLocalId, path}) -> @_verifyId(messageLocalId) @task = new FileUploadTask(path, messageLocalId) @@ -63,9 +63,10 @@ FileUploadStore = Reflux.createStore _onAbortUpload: (uploadData) -> Actions.dequeueMatchingTask({ - object: 'FileUploadTask', - matchKey: "filePath" - matchValue: uploadData.filePath + type: 'FileUploadTask', + matching: { + filePath: uploadData.filePath + } }) _onFileUploaded: ({file, uploadData}) -> diff --git a/src/flux/stores/task-queue.coffee b/src/flux/stores/task-queue.coffee index a67f2e2e6..2979ce2a4 100644 --- a/src/flux/stores/task-queue.coffee +++ b/src/flux/stores/task-queue.coffee @@ -45,9 +45,10 @@ if @_thread && @_thread.isUnread() ```coffee Actions.dequeueMatchingTask({ - object: 'FileUploadTask', - matchKey: "filePath" - matchValue: uploadData.filePath + type: 'FileUploadTask', + matching: { + filePath: uploadData.filePath + } }) ``` @@ -103,11 +104,23 @@ class TaskQueue queue: => @_queue - findTask: ({object, matchKey, matchValue}) -> - for other in @_queue by -1 - if object is object and other[matchKey] is matchValue - return other - return null + ### + Public: Returns an existing task in the queue that matches the type you provide, + and any other match properties. Useful for checking to see if something, like + a "SendDraft" task is in-flight. + + - `type`: The string name of the task class, or the Task class itself. (ie: + {SaveDraftTask} or 'SaveDraftTask') + + - `matching`: Optional An {Object} with criteria to pass to _.isMatch. For a + SaveDraftTask, this could be {draftLocalId: "123123"} + + Returns a matching {Task}, or null. + ### + findTask: (type, matching = {}) -> + type = type.name unless _.isString(type) + match = _.find @_queue, (task) -> task.constructor.name is type and _.isMatch(task, matching) + match ? null enqueue: (task, {silent}={}) => if not (task instanceof Task) @@ -135,8 +148,8 @@ class TaskQueue @dequeue(task, silent: true) if task? @_update() - dequeueMatching: (task) => - toDequeue = @findTask(task) + dequeueMatching: ({type, matching}) => + toDequeue = @findTask(type, matching) if not toDequeue console.warn("Could not find task: #{task?.object}", task) diff --git a/src/tasks/ship-logs-task.coffee b/src/tasks/ship-logs-task.coffee index bc56a3b89..7c82a3fb3 100644 --- a/src/tasks/ship-logs-task.coffee +++ b/src/tasks/ship-logs-task.coffee @@ -31,9 +31,20 @@ module.exports = (dir, regexPattern) -> console.log("Uploading #{logs} to S3") + # The AWS Module does some really interesting stuff - it loads it's configuration + # from JSON files. Unfortunately, when the app is built into an ASAR bundle, child + # processes forked from the main process can't seem to access files inside the archive, + # so AWS can't find it's JSON config. (5/20) + if __dirname.indexOf('app.asar') != -1 + AWSModulePath = path.join(__dirname, '..','..','..', 'app.asar.unpacked', 'node_modules', 'aws-sdk') + else + AWSModulePath = 'aws-sdk' + + console.log("Load AWS module from #{AWSModulePath}") + # Note: These credentials are only good for uploading to this # specific bucket and can't be used for anything else. - AWS = require 'aws-sdk' + AWS = require(AWSModulePath) AWS.config.update accessKeyId: 'AKIAIEGVDSVLK3Z7UVFA', secretAccessKey: '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' diff --git a/src/theme-manager.coffee b/src/theme-manager.coffee index cd9e4f2db..512c8997b 100644 --- a/src/theme-manager.coffee +++ b/src/theme-manager.coffee @@ -32,17 +32,17 @@ class ThemeManager stylesElement.onDidRemoveStyleElement @styleElementRemoved.bind(this) stylesElement.onDidUpdateStyleElement @styleElementUpdated.bind(this) - if atom.inDevMode() and not atom.inSpecMode() - console.log('In Dev Mode - Watching /static for LESS changes') - watchStylesIn = (folder) => - stylePaths = fs.listTreeSync(folder) - PathWatcher = require 'pathwatcher' - for stylePath in stylePaths - continue unless path.extname(stylePath) is '.less' - PathWatcher.watch stylePath, => - @activateThemes() - watchStylesIn("#{@resourcePath}/static") - watchStylesIn("#{@resourcePath}/internal_packages") + watchCoreStyles: -> + console.log('Watching /static and /internal_packages for LESS changes') + watchStylesIn = (folder) => + stylePaths = fs.listTreeSync(folder) + PathWatcher = require 'pathwatcher' + for stylePath in stylePaths + continue unless path.extname(stylePath) is '.less' + PathWatcher.watch stylePath, => + @activateThemes() + watchStylesIn("#{@resourcePath}/static") + watchStylesIn("#{@resourcePath}/internal_packages") styleElementAdded: (styleElement) -> {sheet} = styleElement diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index 1b179d1ad..b364c5078 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -71,6 +71,8 @@ class WindowEventHandler @subscribeToCommand $(window), 'window:toggle-dev-tools', -> atom.toggleDevTools() + @subscribeToCommand $(window), 'window:open-errorreporter-logs', -> atom.errorReporter.openLogs() + if process.platform in ['win32', 'linux'] @subscribeToCommand $(window), 'window:toggle-menu-bar', -> atom.config.set('core.autoHideMenuBar', !atom.config.get('core.autoHideMenuBar'))