For usage notes and API documentation, visit https://macgapproject.github.io/documentation/.
To submit an issue or ask for help, go to the GitHub issue queue at https://github.com/MacGapProject/MacGap2/issues
MacGap 2
License: MIT License
For usage notes and API documentation, visit https://macgapproject.github.io/documentation/.
To submit an issue or ask for help, go to the GitHub issue queue at https://github.com/MacGapProject/MacGap2/issues
I've created a Gitter room for MacGap2, you can find it at: https://gitter.im/MacGapProject/MacGap2 or by clicking on the Gitter badge on the main repo page.
Will the Getting Started / App Configuration sections of the documentation ever be published?
http://docs.macgap.com/doc/app-configuration.html
Or at least, could I get a quick how-to? I can build my app just fine with Xcode but I'm really confused on how to go about changing the name of the project, bundle identifier, etc. I tried changing the name in Xcode but some things did not get updated.
Hello,
I noticed you fixed the issue here: Macmee/macgap@5abbb59
But I'm still having the issue. I'm just doing a simple iframe implementation with just this code:
But when I scroll my headerbar and left menu go bunkers on me.
Thanks in advance for any tips :)
I may have missed this in the docs or misunderstood, but how do I listen for events? For example if the user quits I want to be able to save work in my app before it finishes exiting.
The sound
command in MacGap 1 allowed for multiple sounds to be triggered simultaneously, and their respective callbacks were called on completion.
In MacGap 2, both sounds play but only the last callback is fired. The MG2 code for the Sound
command is beautifully simplified from MG1, but I think something like the MG1 PlayDelegate
is going to still be needed. I'm not certain how this code needs to look in MG2 — will we still simply create a delegate for each sound as its triggered like in MG1?
The following (MG1) JavaScript illustrates the issue:
macgap.sound.playSystem("Blow", function(){
alert('blow finished playing');
});
macgap.sound.playSystem("Funk", function(){
alert('funk finished playing');
});
(In MG2 it's the same code as above except substituting `MacGap.Sound')
This should give two alerts, "funk finished playing" first then "blow finished playing" (since blow is a longer sound). In MG1 this works, in MG2 we only get the "funk finished playing" alert.
A similar situation exists in the Task command as well; subsequent calls to the command overwrite any knowledge of the first.
Hi,
I think it would be good if we could agree on a roadmap and timeline for coordinating our efforts.
When should the MacGap2 website be ready? (Not before MacGap2 is ready?)
When can we start writing the documentation (feature freeze)?
What are the release stages till we get MacGap2 out of the door? (Currently it is labeled alpha but it already feels like beta at least).
What lacks MacGap2 to get to the next stage (alpha => beta)?
Maybe let's use this thread to do some project planning.
Some proposals as a start for discussion:
What do you think?
Cheers Bijan
I haven't quite worked out how to reliably replicate it, but my MG2 app (actually the MG2 Documentation App) crashes quite a lot. I'm not sure what's most useful out of the crash log, or should I post the whole thing?
Here's the start of my most recent one. Or get the full thing
Process: MacGap Documentation [32314]
Path: /Users/USER/*/MacGap Documentation.app/Contents/MacOS/MacGap Documentation
Identifier: com.MacGap-Documentation.docs
Version: 1.0 (1)
Code Type: X86-64 (Native)
Parent Process: launchd [182]
Responsible: MacGap Documentation [32314]
User ID: 503
Date/Time: 2014-06-24 19:51:46.119 +1200
OS Version: Mac OS X 10.9.3 (13D65)
Report Version: 11
Anonymous UUID: 8162CCD8-BAE0-3D32-34AF-595DAB2A3C19
Sleep/Wake UUID: 8720AFE9-1E34-4353-A5D6-48B3AF22C95C
Crashed Thread: 11 Dispatch queue: com.apple.root.background-priority
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: EXC_I386_GPFLT
Application Specific Information:
objc_msgSend() selector name: taskDidTerminate:
I just pushed a branch with the Dock command rewritten in Swift just so you guys can see an example. It's the simplest implementation out of all the commands which is why I picked it to see how everything would port/work. I'll probably add another more complicated command for more in depth example.
I've been playing with the Task() command as follows:
runTask: function() {
var myTask = MacGap.Task.create('/bin/sh', this.myTaskComplete);
myTask.arguments = ['ls'];
myTask.launch();
},
myTaskComplete: function() {
console.log(arguments);
},
The console.log
in myTaskComplete
returns file handles of some kind:
[Log] [ (code.js, line 50)
Object
status: 126
stdErr: NSConcreteFileHandle
__proto__: NSConcreteFileHandlePrototype
stdIn: NSConcreteFileHandle
__proto__: NSConcreteFileHandlePrototype
stdOut: NSConcreteFileHandle
__proto__: NSConcreteFileHandlePrototype
__proto__: Object
]
I'd really like to get the stdout and I am unsure based on our previous discussions about this whether it's possible, or simply not possible with a generic Task
command?
Just wondering if there will be a place in the config file to disable the WebView bounce when scrolling to make it look more like a native app?
Thoughts on rolling in https://github.com/node-app/Nodelike to MacGap 2?
Hi, from the Documentation it is not really clear how to add a Menu with Several Items like "Import Data" or "Export Data".
I tried the following:
var menu = MacGap.Menu.create("crashMe");
menu.addItem({
label:"Hello",
keys:"cmd+g",
index:1,
callback: function(){console.log("Hello")}
});
It crashes Macgap...
What is the correct syntax to add a menu and several items?
Please add a license to the repo, to clarify licensing terms for potential users.
capitalized except the base macgap object, not sure if I should change this or not.
Tricky question! I think I prefer the capitalised version if MacGap.something. It's more natural in a JavaScript context I think?
If we do, it's a simple find-and-replace change from MacGap 1 code.
Previously the window title was bound to the HTML document title. Is there a reason Window.Title() is preferred to the old approach?
Hello,
I have an issue accessing and managing multiple windows from MacGap. I can never get more than 1 extra window (apart from the main) open at one time, all new requests are reloaded in the first extra window. Also, there is no way to access, from the JavaScript DOM, the other windows to change the URL or to dynamically load other content (say from clicking on a menu item). This would be really great to be able to make interactive app with one core to control multiple windows.
I really love this project. If we can be of any help, development or financial, please let me know!
Matthew
It would be awesome to have support for input prompt type dialogs and confirm dialogs similar to https://github.com/apache/cordova-plugin-dialogs/blob/master/doc/index.md
It is great to have a saveDialog but as far as I can tell we still need to be able to actually writeToFile or did I miss something?
I really liked the macgap
gem, as it removed the need for me to manage MacGap itself. I could just focus on my app's code.
Could an official macgap2
gem come into existence and be maintained in some official capacity? It look like at least one person has been updating their fork of the gem.
since there is no page loading status in macgap1, it can be confusing to the user when a page is loading, since there is nothing to show that it is. It would be ideal to have a way to define some sort of overlay or animation that comes up when a page begins loading and disappears when loading is done.
I put together a Meteor integration and build tool example using MacGap2.. https://github.com/meteorhybrid/mac
Also, how active are you on development with this project? Are you looking for more contributors?
We now have a twitter account, so you can keep up to date more easily.
Since there is now some powerful commands like MacGap.Task
, should access to the MacGap object be limited somehow?
Or is it up to the developer to prevent pages that is not under the app's control to load within the app (e.g always use MacGap.openURL
for external links)?
On macgap1 it would open normally. I use that for Facebook auth, so it pretty much got me stuck with the old version, but i'd love to work with macgap2. Beta is thrilling :)
Wondering how people feel about deprecating macgap-rb?
I personally have never used it, as I don't see the point since Xcode is free, and I'm curious how things work. Using Xcode also provides a well-documented environment for doing things like adding your own app icon, and configuring your app for MAS submission.
First, thanks for putting this framework together; allowed me to turn a web app into a POC .app going in one day, despite almost zero Objective-C/Xcode experience. I'm grateful for the work you've put in here!
I am working on a .app that kicks off a bundled long-running subprocess via MacGap.Task
. I'd like the subprocess to run only as long as the .app does, and then shutdown when the .app does. Unfortunately, when I quit the .app, this subprocess is orphaned and runs indefinitely. Is this expected behavior? Relevant code and observations below:
// Launch client
var myTask = MacGap.Task.create(
resources_path+"/the_subprocess",
function(res) {
if (res.status !== 0) {
window.alert("Subprocess failed; exiting.");
MacGap.terminate();
}
}
);
myTask.arguments = ["an_arg"];
myTask.currentDirectoryPath = resources_path;
myTask.waitUntilExit = true; // have tried this both ways
myTask.launch();
According to ps
, the subprocess launches with the .app's pid
as it's ppid
and has no signals masked. It communicates with the .app as expected while the .app is running. Unfortunately, whether I Quit or Force Quit the .app from the Finder, or SIGINT or SIGKILL it from the terminal, the child process is orphaned, assigned to init
, and continues running.
(I also tried registering unload
and beforeunload
handlers to intercept shutdown at the WebKit level and force the cleanup, to no avail, and saw MacGapProject/MacGap1#111, but was not sure what to do based on the inconclusiveness of that issue and my own inexperience in Objective-C/all things NSObject
.)
Any insight would be greatly appreciated–thanks!
As @perifer pointed out in #28 the Task command could benefit from simplification.
At present the JS API reflects the Objective-C mindset where you create a new NSTask instance, then call methods on it to configure it.
A more JavaScript-y API (using jQuery as a model) would probably be:
I propose something like:
var myTask = MacGap.Task.launch('/bin/ls -la /tmp', {
success: myTaskCompleted,
error: myTaskFailed,
});
function myTaskCompleted(stdout) {
console.log(stdout);
};
or else just the one callback:
var myTask = MacGap.Task.launch('/bin/ls -la /tmp', myTaskCompleted);
function myTaskCompleted(resultCode, stdio) {
console.log(stdio);
};
I'm happy to do the refactoring.
I wonder if it would be easier to find the sheet-creation ability if it were in its own top-level command? I didn't expect to find it on the Notify
command.
i.e.
MacGap.Sheet(...);
rather than
MacGap.Notice.notify({
'type' : 'sheet',
...
});
In macgap1 Webkit Developer Tools were available via
"defaults write com.MacGap developer 1"
What would be the way in MacGap2 to debug the js parts of apps?
This code is all looking really nice. Loving how this iteration (the 10.9+ version) is in fact more familiar to those who coded in MG1, but if anything there's less code needed.
Doing away with a bunch of our object translation (objc – js) is looking very nice indeed.
Are you feeling happy to push this into the new MacGapProject organisation? I feel a little presumptuous having not mentioned the possibility of that till now.
Hi, I just finished integrating this cordova plugin with an iPad project, it was pretty easy:
https://github.com/pearj/ExternalScreen-iOS
Would it be possible to do something similar in MacGap2? Has anyone done anything like this yet?
Hi, so when the user clicks the red button in the toolbar on the top left, the app window closes.
I think it's really cool that the user can then click on the dock icon to restore the app window just as it was. Now I'm trying to add a menu item that does the same thing. I've already created the menu item in MainMenu.xib, I just need to give it a callback. So far I have:
MacGap.Menu.getItem("File").submenu.getItem('New Window').callback = function() {
/* ... */
};
I've tried a few things and nothing worked. What should be in the callback?
Code
MacGap.StatusItem.create({
image:"public/[email protected]",
alternateImage: "public/[email protected]",
onClick: function() { console.log('xxxx') }
});
Is there any problem?
So, I discovered today that this isn't implemented yet in MacGap2, and reading a file with type "string" only works for text files.
After about 4 hours of trying various things and banging my head against the wall, I've come up with an implementation that works for me, and figured I would share it here. It might not be what you had in mind for type "image" but it actually works for any type of file.
NSData* imgData = [NSData dataWithContentsOfFile:filePath];
NSString* val = [imgData base64EncodedString];
return [JSValue valueWithObject:val inContext:[JSContext currentContext]];
Why am I returning raw file data as a base64EncodedString? Well, in my JS code I read GIF files as ArrayBuffers and do a bunch of magic to convert the frames into individual images, which I then inject into the DOM as img tags with the src for each img tag being a data URL of type image/png. I already had functions for reading GIF files from the Internet using XMLHTTPRequest with a type of ArrayBuffer, so I needed something similar for reading files off disk to reuse as much code as possible. And, in my JS I can easily convert a base64EncodedString representing the raw data of a GIF file into an ArrayBuffer, so returning a base64EncodedString from the JS bridge in Obj-C was really ideal, and it's nice that the end result was just 2 lines of Obj-C code (even though it took 4 hours to write those 2 lines).
Anyway, sorry for the long story but this could be a nice way to handle file reading (either as a default type or for type "image" or even a new type, "raw"), and I would be happy to submit a PR with my code.
Hi, I am modifying a default menu item File > Open...
The following works fine:
MacGap.Menu.getItem("File").submenu.getItem('Open').callback = uploadHandler;
The following, immediately after, doesn't do anything. No error, nothing:
MacGap.Menu.getItem("File").submenu.getItem('Open').enabled = false;
What am I doing wrong?
The notify command appears to have regressed a little since MG1.
We no longer have:
sound
key for the dictionary/object passed into notifyclose
method@rawcreative — are you happy for me to remove the gh-pages branch from /MacGap2 and push it to the /documentation branch?
I saw in the other project that the idea for tabs was shot down quickly. But I see a good use for it. For example, I am using this for a groupware application, similar to SeaMonkey. We have an email client and company intranet among other things. I can see a good use for multiple tabs, each with its own index.html so we can present multiple web apps in 1 window.
It's hard to explain, but this would be a great and simple addition to make the application appear more like your own and not a web view. Here's the link to what I am talking about more. http://stackoverflow.com/questions/25250762/xcode-swift-window-without-title-bar-but-with-close-minimize-and-resize-but
Is there any way to get this working with MacGap2? I cannot seem to get the WebViewJavascriptBridge working. Is there an easier way? Thanks! https://github.com/MacGapProject/MacGap1/wiki/Add-NSToolbar-to-MacGap-application
I was surprised that openDialog didn't support limiting the allowed file types so I added support. This is the method now:
- (void) openDialog:(JSValue *)args
{
context = [JSContext currentContext];
NSOpenPanel * openDlg = [NSOpenPanel openPanel];
JSValue* mult = [args valueForProperty:@"multiple"];
JSValue* files = [args valueForProperty:@"files"];
JSValue* dirs = [args valueForProperty:@"directories"];
JSValue* cb = [args valueForProperty: @"callback"];
JSValue* allowedTypes = [args valueForProperty:@"allowedTypes"];
[openDlg setCanChooseFiles: [files toBool]];
[openDlg setCanChooseDirectories: [dirs toBool]];
[openDlg setAllowsMultipleSelection: [mult toBool]];
if(allowedTypes)
[openDlg setAllowedFileTypes: [allowedTypes toArray]];
[openDlg beginWithCompletionHandler:^(NSInteger result){
if (result == NSFileHandlingPanelOKButton) {
if(cb) {
NSArray* files = [[openDlg URLs] valueForKey:@"relativePath"];
[cb callWithArguments: @[files]];
}
}
}];
}
and I can call the method with the extra allowedTypes argument:
MacGap.Dialog.openDialog({files:true,multiple:true,directories:false,allowedTypes:['gif'],callback:function(files){
insertFilesMacGap(files);
}});
Launchbar has some interesting stuff in their API, e.g HTTP: http://www.obdev.at/resources/launchbar/developer-documentation/javascript-http.html
I'm guessing similar functionality could be useful in a MacGap context, since XMLHttpRequest are restricted by Same-origin policy.
Hey is it possible to make a Button that was added via IB to emit a javascript signal?
Can this be done and if so how?
This would open new ways for Native Interfaces.
Cheers Bijan
PS: MacGap2 is great!
How to set the initial size and position of the window. Even before the window loads. I didn't find any docs on that.
Thanks in advance.
I can't write Objective-C at all, but from what I can tell idleTime
has only been partially implemented. A header exists, as does a function to retrieve it, but it's not connected up to the App
object.
When you compile the app, Xcode 6 complains about being unable to synthesize such-and-such.
Hi,
came across this project and decided to give it a go. Works pretty good but something is going wrong when trying to resize a window.
Steps to reproduce:
<meta http-equiv="refresh" content="2;URL=https://www.google.com">
or any other url/time combination8/10/2014 7:13:14.467 am MG[6621]: -[__NSCFData defaultsChanged:]: unrecognized selector sent to instance 0x600000458240
Can provide log via email if you want?
Apple has added something very intriguing to OS X 10.10. I guess this would eventually replace AppleScript but also looks very interesting in light of what we are doing.
Contains amongst other stuff an Objective-C Bridge with the following example provided:
ObjC.import('Cocoa')
$.NSBeep()
and...
For instance, this instantiates an NSString from a JavaScript string and writes it to a file:
str = $.NSMutableString.alloc.init
str = $.NSString.alloc.initWithUTF8String('foo')
str.writeToFileAtomically('/tmp/foo', true)
Is MacGap 2 at a point where you would like us to start testing it? Could you identify what you would like to happen before it moves from alpha to beta, and from beta to release?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.