Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use a file based startup on darwin #38

Merged
merged 4 commits into from
Sep 16, 2016
Merged

use a file based startup on darwin #38

merged 4 commits into from
Sep 16, 2016

Conversation

noamokman
Copy link
Contributor

Hi there!
Should close #25 #28 #31

Thanks!

@noamokman
Copy link
Contributor Author

@adam-lynch would love your opinion 😄

file = @getFile(opts)
array = [opts.appPath]
if(opts.isHiddenOnLaunch) then array.push('--hidden')
command = array.map(a => ` <string>${a}</string>`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait... backticks in CoffeeScript? Never saw this before. I thought you had to use double quotes for interpolation.

@adam-lynch
Copy link
Contributor

Thanks. Educate me... what are the pros & cons of this versus the existing way?

If we did change it, what about app's that were using the old version? How do they transition to this? Do we need to keep the old logic in this module and transition it to file-based?

@noamokman
Copy link
Contributor Author

Thanks for the remarks!
Fixed the problematic bits.
Also removed the applescript dep.

I think this should be a breaking change,
so we wont have to deal with mixed implementation.

As for pros and cons,
It seems that the current way has problems with a terminal window popping up.
I believe this will work better

P.S,
This unifies the --hidden argument being sent on all platforms,
so it's already a good enough reason to bump major.
Maybe write more clearly that the hidden option sends this --hidden arg on startup,
and that is up for the developer to use relevant logic based on the args.

@dcposch
Copy link

dcposch commented Aug 31, 2016

It seems that the current way has problems with a terminal window popping up.

Are there projects that support Mac and use auto-launch in production?

I'm surprised this hasn't come up before--it seems like opening an extra terminal window after every boot would result in lots of user feedback & bug reports. (Esp since closing the terminal window then kills the app.)

@adam-lynch
Copy link
Contributor

@dcposch I can say yes definitely with NW.js but can't confirm Electron but I assume so?

@noamokman I'll take a proper look at this soon. In the meantime, maybe others could confirm this is OK for them / solves their problems? I'll ask in the issues you've linked

@mzdr
Copy link

mzdr commented Sep 1, 2016

Hey @noamokman, your patch gives me the following error:

Promise {
  <rejected> ReferenceError: name is not defined
    at /Users/sp/Projects/timestamp/node_modules/auto-launch/dist/AutoLaunchMac.js:29:236
    at Object.enable (/Users/sp/Projects/timestamp/node_modules/auto-launch/dist/AutoLaunchMac.js:18:12)
    at AutoLaunch.module.exports.AutoLaunch.enable (/Users/sp/Projects/timestamp/node_modules/auto-launch/dist/index.js:72:21)
    at new App (/Users/sp/Projects/timestamp/app/app.js:45:39)
    at App.Electron.app.on (/Users/sp/Projects/timestamp/app/index.js:7:32)
    at emitOne (events.js:101:20)
    at App.emit (events.js:188:7) }

Have a look at https://github.com/Teamwork/node-auto-launch/pull/38/files#diff-3cb4ac24dd2f84b466e7af980f600036R25. Or am I wrong?

<plist version="1.0">
<dict>
<key>Label</key>
<string>#{name}</string>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting ReferenceError: name is not defined here…

@noamokman
Copy link
Contributor Author

@mzdr oops, please try again,
Thanks!

@mzdr
Copy link

mzdr commented Sep 2, 2016

Out of the box it's not working on my machine (Electron v1.3.4 and OSX 10.11.6). There is no .plist file being written and I don't get any errors. I am debugging right now…


module.exports =
getFile: (opts) ->
file = dir+opts.appName+'.plist'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@noamokman I think there is a / missing here because I keep getting file paths like this: /Users/sp/Library/LaunchAgentsMinecraft.plist

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great catch! thanks for the help 😄

@noamokman
Copy link
Contributor Author

@mzdr added the missing /

@mzdr
Copy link

mzdr commented Sep 2, 2016

Okay, now it seems to be working. After logging out and back in again my app was automatically started. 👍

Though I personally have some concerns with the LaunchAgent approach. For example if you delete an app which was set to auto launch, the .plist file will end up as a dead file on the users hard disk. I know it’s picky, but nevertheless it’s something we should care about.

Furthermore the average (or more sophisticated) user will probably check his login items under System Preferences → Users & Groups → Login Items and delete old/non-existent apps from there. But apps registered as a LaunchAgent won’t show up there.

@adam-lynch I think this is something we should consider.

@noamokman
Copy link
Contributor Author

Though I personally have some concerns with the LaunchAgent approach. For example if you delete an app which was set to auto launch, the .plist file will end up as a dead file on the users hard disk. I know it’s picky, but nevertheless it’s something we should care about.

@mzdr
This is also true for the linux implementation.

@dcposch
Copy link

dcposch commented Sep 6, 2016

@mzdr @adam-lynch Thoughts?

For WebTorrent Desktop, we can't use auto-launch as long as it's creating a terminal window on Mac.

@mzdr
Copy link

mzdr commented Sep 8, 2016

@dcposch Did you checkout the workaround posted in #28? As for now I'm using auto-launch with the workaround as well…

@dcposch
Copy link

dcposch commented Sep 10, 2016

@mzdr yeah, I tried the workaround for Electron listed here:

#28 (comment)

Didn't work

@adam-lynch
Copy link
Contributor

OK I'm going to test this tonight/tomorrow. I'll give it a quick review now.

Copy link
Contributor

@adam-lynch adam-lynch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again 👍

applescript.execString command, (err) ->
new Promise (resolve, reject) =>
file = @getFile(opts)
array = [opts.appPath]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't call this array

new Promise (resolve, reject) =>
file = @getFile(opts)
array = [opts.appPath]
if(opts.isHiddenOnLaunch) then array.push('--hidden')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need the then; you can do this:

array.push('--hidden') if opts.isHiddenOnLaunch

</dict>
</plist>"""

mkdirp.sync(dir)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we have some error checking here?

return reject(err) if err?
resolve()

disable: (opts) ->
new Promise (resolve, reject) ->
command = tellTo + "delete login item \"#{opts.appName}\""
new Promise (resolve, reject) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're touching these lines (where new Promise is returned), do you mind adding a return at the start? I'm not a fan of using implicit returns in multi-line functions

return reject(err) if err?
resolve()
fs.unlink file, (err2) ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is silly but name it something other than err2. Even if it's error or something.

isPresent = loginItems?.indexOf(opts.appName)
resolve(isPresent? and isPresent isnt -1)
fs.stat file, (err, stat) ->
# TODO: Error handling
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to reject here.

Copy link
Contributor

@adam-lynch adam-lynch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I've tested it and it's fine except if you call disable when it's not enabled, it'll reject with an error about a missing file. It should resolve in this case.

@adam-lynch
Copy link
Contributor

One other thing I noticed is that the app doesn't appear in the user's Login Items (in system preferences).

screen shot 2016-09-16 at 17 54 13

I'm confirming with some proper Mac users to see if that would annoy users.

I'm guessing it's fine. Once this is merged, I'll add a note about it to the README along with one about the leftover file if the user deletes the app.

@adam-lynch
Copy link
Contributor

OK I got great information from @chillok. We think it's not bad that it doesn't appear in Login Items (even though it's not nice) but he let me know that this definitely isn't Mac App Store friendly. An app using this would be rejected because it reaches outside of the app sandbox. See https://developer.apple.com/library/content/documentation/Security/Conceptual/AppSandboxDesignGuide/AboutAppSandbox/AboutAppSandbox.html for more info.

About sandboxing

App sandbox directories

At first, I thought this was a deal-breaker for this PR but we think the existing method (executing an applescript command) isn't MAS friendly either so we'll go with this PR.

I guess that's just something else I'll have to add to our README.


I know someone will end up coming to this comment in the future after googling so I'll say it is possible to have an auto-launching app in the Mac App Store. See http://martiancraft.com/blog/2015/01/login-items/. As long as it doesn't auto-launch by default, the user can toggle it, etc. You need to have a separate app/executable for this so since that means native code and that extra app/executable would have to be signed just like your main app would, this module would never be able to handle that. I'll create a feature request over on electron-builder (as it already handles the signing of Electron apps for you) but I'm not 100% sure it's possible because a user preference is needed. NW.js and Electron might have to add this.

@adam-lynch
Copy link
Contributor

Here it is: electron-userland/electron-builder#756

@adam-lynch adam-lynch merged commit 0187f7f into Teamwork:master Sep 16, 2016
@adam-lynch
Copy link
Contributor

OK after some more overthinking... I'm going to make this an option. So I've merged this as is and I'll sort it out.

@adam-lynch
Copy link
Contributor

OK I've overhauled this module a bit. There's now a mac.useLaunchAgent option. See https://github.com/Teamwork/node-auto-launch/releases/tag/5.0.0. Thanks for the PR @noamokman 👍

@noamokman
Copy link
Contributor Author

@adam-lynch thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Can't get correct isEnabled() result in menu click function (only on mac)
4 participants