mirror of
https://github.com/taigrr/wails.git
synced 2026-04-04 22:22:41 -07:00
Compare commits
16 Commits
v2.0.0-alp
...
v2.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5e76c50b0 | ||
|
|
e40226ff7a | ||
|
|
53a3638fa8 | ||
|
|
1344638c52 | ||
|
|
6fdc87454a | ||
|
|
c36f9501a9 | ||
|
|
c23b43c352 | ||
|
|
a76851463b | ||
|
|
e17b432c8f | ||
|
|
5d444cd6dd | ||
|
|
be43049fc6 | ||
|
|
2e01710412 | ||
|
|
1b0193161c | ||
|
|
1b377fb575 | ||
|
|
1203ae64b8 | ||
|
|
26ed8002b9 |
@@ -54,6 +54,10 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
ldflags := ""
|
||||
command.StringFlag("ldflags", "optional ldflags", &ldflags)
|
||||
|
||||
// tags to pass to `go`
|
||||
tags := ""
|
||||
command.StringFlag("tags", "tags to pass to Go compiler (quoted and space separated)", &tags)
|
||||
|
||||
// Log to file
|
||||
//logFile := ""
|
||||
//command.StringFlag("l", "Log to file", &logFile)
|
||||
@@ -121,6 +125,16 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
println("Warning: compress flag unsupported for universal binaries. Ignoring.")
|
||||
compress = false
|
||||
}
|
||||
|
||||
// Tags
|
||||
userTags := []string{}
|
||||
for _, tag := range strings.Split(tags, " ") {
|
||||
thisTag := strings.TrimSpace(tag)
|
||||
if thisTag != "" {
|
||||
userTags = append(userTags, thisTag)
|
||||
}
|
||||
}
|
||||
|
||||
// Create BuildOptions
|
||||
buildOptions := &build.Options{
|
||||
Logger: logger,
|
||||
@@ -135,6 +149,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
AppleIdentity: appleIdentity,
|
||||
Verbosity: verbosity,
|
||||
Compress: compress,
|
||||
UserTags: userTags,
|
||||
}
|
||||
|
||||
// Calculate platform and arch
|
||||
@@ -166,6 +181,7 @@ func AddBuildSubcommand(app *clir.Cli, w io.Writer) {
|
||||
fmt.Fprintf(w, "Clean Build Dir: \t%t\n", buildOptions.CleanBuildDirectory)
|
||||
fmt.Fprintf(w, "KeepAssets: \t%t\n", buildOptions.KeepAssets)
|
||||
fmt.Fprintf(w, "LDFlags: \t\"%s\"\n", buildOptions.LDFlags)
|
||||
fmt.Fprintf(w, "Tags: \t[%s]\n", strings.Join(buildOptions.UserTags, ","))
|
||||
if len(buildOptions.OutputFile) > 0 {
|
||||
fmt.Fprintf(w, "Output File: \t%s\n", buildOptions.OutputFile)
|
||||
}
|
||||
|
||||
@@ -67,5 +67,6 @@ func main() {
|
||||
err = app.Run()
|
||||
if err != nil {
|
||||
println("\n\nERROR: " + err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
package main
|
||||
|
||||
var version = "v2.0.0-alpha.61"
|
||||
var version = "v2.0.0-alpha.64"
|
||||
|
||||
@@ -4,13 +4,13 @@ go 1.16
|
||||
|
||||
require (
|
||||
github.com/Masterminds/semver v1.5.0
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/fatih/structtag v1.2.0
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/gorilla/websocket v1.4.1
|
||||
github.com/imdario/mergo v0.3.11
|
||||
github.com/jackmordaunt/icns v1.0.0
|
||||
github.com/leaanthony/clir v1.0.4
|
||||
github.com/leaanthony/go-ansi-parser v1.0.1
|
||||
github.com/leaanthony/gosod v0.0.4
|
||||
github.com/leaanthony/slicer v1.5.0
|
||||
github.com/matryer/is v1.4.0
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||
@@ -42,6 +41,8 @@ github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eT
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/leaanthony/clir v1.0.4 h1:Dov2y9zWJmZr7CjaCe86lKa4b5CSxskGAt2yBkoDyiU=
|
||||
github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
|
||||
github.com/leaanthony/go-ansi-parser v1.0.1 h1:97v6c5kYppVsbScf4r/VZdXyQ21KQIfeQOk2DgKxGG4=
|
||||
github.com/leaanthony/go-ansi-parser v1.0.1/go.mod h1:7arTzgVI47srICYhvgUV4CGd063sGEeoSlych5yeSPM=
|
||||
github.com/leaanthony/gosod v0.0.4 h1:v4hepo4IyL8E8c9qzDsvYcA0KGh7Npf8As74K5ibQpI=
|
||||
github.com/leaanthony/gosod v0.0.4/go.mod h1:nGMCb1PJfXwBDbOAike78jEYlpqge+xUKFf0iBKjKxU=
|
||||
github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY=
|
||||
|
||||
@@ -24,6 +24,9 @@ struct hashmap_s dialogIconCache;
|
||||
// Dispatch Method
|
||||
typedef void (^dispatchMethod)(void);
|
||||
|
||||
// Message Dialog
|
||||
void MessageDialog(struct Application *app, char *callbackID, char *type, char *title, char *message, char *icon, char *button1, char *button2, char *button3, char *button4, char *defaultButton, char *cancelButton);
|
||||
|
||||
TrayMenuStore *TrayMenuStoreSingleton;
|
||||
|
||||
// dispatch will execute the given `func` pointer
|
||||
@@ -80,6 +83,11 @@ void ShowMouse() {
|
||||
msg_reg(c("NSCursor"), s("unhide"));
|
||||
}
|
||||
|
||||
OSVersion getOSVersion() {
|
||||
id processInfo = msg_reg(c("NSProcessInfo"), s("processInfo"));
|
||||
return GET_OSVERSION(processInfo);
|
||||
}
|
||||
|
||||
struct Application {
|
||||
|
||||
// Cocoa data
|
||||
@@ -295,7 +303,11 @@ void messageHandler(id self, SEL cmd, id contentController, id message) {
|
||||
const char *name = (const char *)msg_reg(msg_reg(message, s("name")), s("UTF8String"));
|
||||
if( strcmp(name, "error") == 0 ) {
|
||||
printf("There was a Javascript error. Please open the devtools for more information.\n");
|
||||
Show(app);
|
||||
// Show app if we are in debug mode
|
||||
if( debug ) {
|
||||
Show(app);
|
||||
MessageDialog(app, "", "error", "Javascript Error", "There was a Javascript error. Please open the devtools for more information.", "", "", "", "","","","");
|
||||
}
|
||||
} else if( strcmp(name, "completed") == 0) {
|
||||
// Delete handler
|
||||
msg_id(app->manager, s("removeScriptMessageHandlerForName:"), str("completed"));
|
||||
@@ -691,7 +703,7 @@ void processDialogButton(id alert, char *buttonTitle, char *cancelButton, char *
|
||||
}
|
||||
}
|
||||
|
||||
extern void MessageDialog(struct Application *app, char *callbackID, char *type, char *title, char *message, char *icon, char *button1, char *button2, char *button3, char *button4, char *defaultButton, char *cancelButton) {
|
||||
void MessageDialog(struct Application *app, char *callbackID, char *type, char *title, char *message, char *icon, char *button1, char *button2, char *button3, char *button4, char *defaultButton, char *cancelButton) {
|
||||
// Guard against calling during shutdown
|
||||
if( app->shuttingDown ) return;
|
||||
|
||||
@@ -791,18 +803,20 @@ extern void MessageDialog(struct Application *app, char *callbackID, char *type,
|
||||
buttonPressed = button4;
|
||||
}
|
||||
|
||||
// Construct callback message. Format "DM<callbackID>|<selected button index>"
|
||||
const char *callback = concat("DM", callbackID);
|
||||
const char *header = concat(callback, "|");
|
||||
const char *responseMessage = concat(header, buttonPressed);
|
||||
if ( STR_HAS_CHARS(callbackID) ) {
|
||||
// Construct callback message. Format "DM<callbackID>|<selected button index>"
|
||||
const char *callback = concat("DM", callbackID);
|
||||
const char *header = concat(callback, "|");
|
||||
const char *responseMessage = concat(header, buttonPressed);
|
||||
|
||||
// Send message to backend
|
||||
app->sendMessageToBackend(responseMessage);
|
||||
// Send message to backend
|
||||
app->sendMessageToBackend(responseMessage);
|
||||
|
||||
// Free memory
|
||||
MEMFREE(header);
|
||||
MEMFREE(callback);
|
||||
MEMFREE(responseMessage);
|
||||
// Free memory
|
||||
MEMFREE(header);
|
||||
MEMFREE(callback);
|
||||
MEMFREE(responseMessage);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1698,9 +1712,6 @@ void HasURLHandlers(struct Application* app) {
|
||||
void Quit(struct Application *app) {
|
||||
Debug(app, "Quit Called");
|
||||
msg_id(app->application, s("stop:"), NULL);
|
||||
SetSize(app, 0, 0);
|
||||
Show(app);
|
||||
Hide(app);
|
||||
}
|
||||
|
||||
id createImageFromBase64Data(const char *data, bool isTemplateImage) {
|
||||
|
||||
@@ -11,6 +11,12 @@
|
||||
#include "hashmap.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
typedef struct {
|
||||
long maj;
|
||||
long min;
|
||||
long patch;
|
||||
} OSVersion;
|
||||
|
||||
// Macros to make it slightly more sane
|
||||
#define msg objc_msgSend
|
||||
#define msg_reg ((id(*)(id, SEL))objc_msgSend)
|
||||
@@ -37,11 +43,13 @@
|
||||
#if defined (__aarch64__)
|
||||
#define GET_FRAME(receiver) ((CGRect(*)(id, SEL))objc_msgSend)(receiver, s("frame"))
|
||||
#define GET_BOUNDS(receiver) ((CGRect(*)(id, SEL))objc_msgSend)(receiver, s("bounds"))
|
||||
#define GET_OSVERSION(receiver) ((OSVersion(*)(id, SEL))objc_msgSend)(processInfo, s("operatingSystemVersion"));
|
||||
#endif
|
||||
|
||||
#if defined (__x86_64__)
|
||||
#define GET_FRAME(receiver) ((CGRect(*)(id, SEL))objc_msgSend_stret)(receiver, s("frame"))
|
||||
#define GET_BOUNDS(receiver) ((CGRect(*)(id, SEL))objc_msgSend_stret)(receiver, s("bounds"))
|
||||
#define GET_OSVERSION(receiver) ((OSVersion(*)(id, SEL))objc_msgSend_stret)(processInfo, s("operatingSystemVersion"));
|
||||
#endif
|
||||
|
||||
#define GET_BACKINGSCALEFACTOR(receiver) ((CGFloat(*)(id, SEL))objc_msgSend)(receiver, s("backingScaleFactor"))
|
||||
|
||||
@@ -189,6 +189,9 @@ id processAcceleratorKey(const char *key) {
|
||||
if( STREQ(key, "return") ) {
|
||||
return strunicode(0x000d);
|
||||
}
|
||||
if( STREQ(key, "enter") ) {
|
||||
return strunicode(0x000d);
|
||||
}
|
||||
if( STREQ(key, "escape") ) {
|
||||
return strunicode(0x001b);
|
||||
}
|
||||
@@ -576,32 +579,127 @@ id processCheckboxMenuItem(Menu *menu, id parentmenu, const char *title, const c
|
||||
return item;
|
||||
}
|
||||
|
||||
// getColour returns the colour from a styledLabel based on the key
|
||||
const char* getColour(JsonNode *styledLabelEntry, const char* key) {
|
||||
JsonNode* colEntry = getJSONObject(styledLabelEntry, key);
|
||||
if( colEntry == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
return getJSONString(colEntry, "hex");
|
||||
}
|
||||
|
||||
id createAttributedStringFromStyledLabel(JsonNode *styledLabel, const char* fontName, int fontSize) {
|
||||
|
||||
// Create result
|
||||
id attributedString = ALLOC_INIT("NSMutableAttributedString");
|
||||
msg_reg(attributedString, s("autorelease"));
|
||||
|
||||
// Create new Dictionary
|
||||
id dictionary = ALLOC_INIT("NSMutableDictionary");
|
||||
msg_reg(dictionary, s("autorelease"));
|
||||
|
||||
// Use default font
|
||||
CGFloat fontSizeFloat = (CGFloat)fontSize;
|
||||
id font = ((id(*)(id, SEL, CGFloat))objc_msgSend)(c("NSFont"), s("menuBarFontOfSize:"), fontSizeFloat);
|
||||
|
||||
// Check user supplied font
|
||||
if( STR_HAS_CHARS(fontName) ) {
|
||||
id fontNameAsNSString = str(fontName);
|
||||
id userFont = ((id(*)(id, SEL, id, CGFloat))objc_msgSend)(c("NSFont"), s("fontWithName:size:"), fontNameAsNSString, fontSizeFloat);
|
||||
if( userFont != NULL ) {
|
||||
font = userFont;
|
||||
}
|
||||
}
|
||||
|
||||
id fan = lookupStringConstant(str("NSFontAttributeName"));
|
||||
id NSForegroundColorAttributeName = lookupStringConstant(str("NSForegroundColorAttributeName"));
|
||||
id NSBackgroundColorAttributeName = lookupStringConstant(str("NSBackgroundColorAttributeName"));
|
||||
|
||||
// Loop over styled text creating NSAttributedText and appending to result
|
||||
JsonNode *styledLabelEntry;
|
||||
json_foreach(styledLabelEntry, styledLabel) {
|
||||
|
||||
// Clear dictionary
|
||||
msg_reg(dictionary, s("removeAllObjects"));
|
||||
|
||||
// Add font to dictionary
|
||||
msg_id_id(dictionary, s("setObject:forKey:"), font, fan);
|
||||
|
||||
// Get Text
|
||||
const char* thisLabel = mustJSONString(styledLabelEntry, "Label");
|
||||
|
||||
// Get foreground colour
|
||||
const char *hexColour = getColour(styledLabelEntry, "FgCol");
|
||||
if( hexColour != NULL) {
|
||||
unsigned short r, g, b, a;
|
||||
|
||||
// white by default
|
||||
r = g = b = a = 255;
|
||||
int count = sscanf(hexColour, "#%02hx%02hx%02hx%02hx", &r, &g, &b, &a);
|
||||
if (count > 0) {
|
||||
id colour = ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)(c("NSColor"), s("colorWithCalibratedRed:green:blue:alpha:"),
|
||||
(CGFloat)r / (CGFloat)255.0,
|
||||
(CGFloat)g / (CGFloat)255.0,
|
||||
(CGFloat)b / (CGFloat)255.0,
|
||||
(CGFloat)a / (CGFloat)255.0);
|
||||
msg_id_id(dictionary, s("setObject:forKey:"), colour, NSForegroundColorAttributeName);
|
||||
}
|
||||
}
|
||||
|
||||
// Get background colour
|
||||
hexColour = getColour(styledLabelEntry, "BgCol");
|
||||
if( hexColour != NULL) {
|
||||
unsigned short r, g, b, a;
|
||||
|
||||
// white by default
|
||||
r = g = b = a = 255;
|
||||
int count = sscanf(hexColour, "#%02hx%02hx%02hx%02hx", &r, &g, &b, &a);
|
||||
if (count > 0) {
|
||||
id colour = ((id(*)(id, SEL, CGFloat, CGFloat, CGFloat, CGFloat))objc_msgSend)(c("NSColor"), s("colorWithCalibratedRed:green:blue:alpha:"),
|
||||
(CGFloat)r / (CGFloat)255.0,
|
||||
(CGFloat)g / (CGFloat)255.0,
|
||||
(CGFloat)b / (CGFloat)255.0,
|
||||
(CGFloat)a / (CGFloat)255.0);
|
||||
msg_id_id(dictionary, s("setObject:forKey:"), colour, NSForegroundColorAttributeName);
|
||||
}
|
||||
}
|
||||
|
||||
// Create AttributedText
|
||||
id thisString = ALLOC("NSMutableAttributedString");
|
||||
msg_reg(thisString, s("autorelease"));
|
||||
msg_id_id(thisString, s("initWithString:attributes:"), str(thisLabel), dictionary);
|
||||
|
||||
// Append text to result
|
||||
msg_id(attributedString, s("appendAttributedString:"), thisString);
|
||||
}
|
||||
|
||||
return attributedString;
|
||||
|
||||
}
|
||||
|
||||
|
||||
id createAttributedString(const char* title, const char* fontName, int fontSize, const char* RGBA) {
|
||||
|
||||
// Process Menu Item attributes
|
||||
// Create new Dictionary
|
||||
id dictionary = ALLOC_INIT("NSMutableDictionary");
|
||||
|
||||
// Process font
|
||||
CGFloat fontSizeFloat = (CGFloat)fontSize;
|
||||
|
||||
// Check if valid
|
||||
id fontNameAsNSString = str(fontName);
|
||||
id font = ((id(*)(id, SEL, id, CGFloat))objc_msgSend)(c("NSFont"), s("fontWithName:size:"), fontNameAsNSString, fontSizeFloat);
|
||||
if( font == NULL ) {
|
||||
bool supportsMonospacedDigitSystemFont = (bool) ((id(*)(id, SEL, SEL))objc_msgSend)(c("NSFont"), s("respondsToSelector:"), s("monospacedDigitSystemFontOfSize:weight:"));
|
||||
if( supportsMonospacedDigitSystemFont ) {
|
||||
font = ((id(*)(id, SEL, CGFloat, CGFloat))objc_msgSend)(c("NSFont"), s("monospacedDigitSystemFontOfSize:weight:"), fontSizeFloat, (CGFloat)NSFontWeightRegular);
|
||||
} else {
|
||||
font = ((id(*)(id, SEL, CGFloat))objc_msgSend)(c("NSFont"), s("menuFontOfSize:"), fontSizeFloat);
|
||||
// Use default font
|
||||
id font = ((id(*)(id, SEL, CGFloat))objc_msgSend)(c("NSFont"), s("menuBarFontOfSize:"), fontSizeFloat);
|
||||
|
||||
// Check user supplied font
|
||||
if( STR_HAS_CHARS(fontName) ) {
|
||||
id fontNameAsNSString = str(fontName);
|
||||
id userFont = ((id(*)(id, SEL, id, CGFloat))objc_msgSend)(c("NSFont"), s("fontWithName:size:"), fontNameAsNSString, fontSizeFloat);
|
||||
if( userFont != NULL ) {
|
||||
font = userFont;
|
||||
}
|
||||
}
|
||||
|
||||
// Add font to dictionary
|
||||
id fan = lookupStringConstant(str("NSFontAttributeName"));
|
||||
msg_id_id(dictionary, s("setObject:forKey:"), font, fan);
|
||||
id offset = msg_float(c("NSNumber"), s("numberWithFloat:"), (float)0.0);
|
||||
id offsetAttrName = lookupStringConstant(str("NSBaselineOffsetAttributeName"));
|
||||
msg_id_id(dictionary, s("setObject:forKey:"), offset, offsetAttrName);
|
||||
|
||||
// RGBA
|
||||
if( RGBA != NULL && strlen(RGBA) > 0) {
|
||||
unsigned short r, g, b, a;
|
||||
@@ -627,7 +725,7 @@ id createAttributedString(const char* title, const char* fontName, int fontSize,
|
||||
return attributedString;
|
||||
}
|
||||
|
||||
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA, bool templateImage, bool alternate) {
|
||||
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA, bool templateImage, bool alternate, JsonNode* styledLabel) {
|
||||
id item = ALLOC("NSMenuItem");
|
||||
|
||||
// Create a MenuItemCallbackData
|
||||
@@ -654,7 +752,12 @@ id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char
|
||||
msg_id(item, s("setImage:"), nsimage);
|
||||
}
|
||||
|
||||
id attributedString = createAttributedString(title, fontName, fontSize, RGBA);
|
||||
id attributedString = NULL;
|
||||
if( styledLabel != NULL) {
|
||||
attributedString = createAttributedStringFromStyledLabel(styledLabel, fontName, fontSize);
|
||||
} else {
|
||||
attributedString = createAttributedString(title, fontName, fontSize, RGBA);
|
||||
}
|
||||
msg_id(item, s("setAttributedTitle:"), attributedString);
|
||||
|
||||
//msg_id(item, s("setTitle:"), str(title));
|
||||
@@ -701,6 +804,8 @@ void processMenuItem(Menu *menu, id parentMenu, JsonNode *item) {
|
||||
label = "(empty)";
|
||||
}
|
||||
|
||||
// Check for a styled label
|
||||
JsonNode *styledLabel = getJSONObject(item, "StyledLabel");
|
||||
|
||||
// Is this an alternate menu item?
|
||||
bool alternate = false;
|
||||
@@ -760,7 +865,7 @@ void processMenuItem(Menu *menu, id parentMenu, JsonNode *item) {
|
||||
JsonNode *type = json_find_member(item, "Type");
|
||||
if( type != NULL ) {
|
||||
if( STREQ(type->string_, "Text") || STREQ(type->string_, "Submenu")) {
|
||||
id thisMenuItem = processTextMenuItem(menu, parentMenu, label, menuid, disabled, acceleratorkey, modifiers, tooltip, image, fontName, fontSize, RGBA, templateImage, alternate);
|
||||
id thisMenuItem = processTextMenuItem(menu, parentMenu, label, menuid, disabled, acceleratorkey, modifiers, tooltip, image, fontName, fontSize, RGBA, templateImage, alternate, styledLabel);
|
||||
|
||||
// Check if this node has a submenu
|
||||
JsonNode *submenu = json_find_member(item, "SubMenu");
|
||||
|
||||
@@ -105,12 +105,13 @@ id processRadioMenuItem(Menu *menu, id parentmenu, const char *title, const char
|
||||
|
||||
id processCheckboxMenuItem(Menu *menu, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *key);
|
||||
|
||||
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA, bool templateImage, bool alternate);
|
||||
id processTextMenuItem(Menu *menu, id parentMenu, const char *title, const char *menuid, bool disabled, const char *acceleratorkey, const char **modifiers, const char* tooltip, const char* image, const char* fontName, int fontSize, const char* RGBA, bool templateImage, bool alternate, JsonNode* styledLabel);
|
||||
void processMenuItem(Menu *menu, id parentMenu, JsonNode *item);
|
||||
void processMenuData(Menu *menu, JsonNode *menuData);
|
||||
|
||||
void processRadioGroupJSON(Menu *menu, JsonNode *radioGroup);
|
||||
id GetMenu(Menu *menu);
|
||||
id createAttributedString(const char* title, const char* fontName, int fontSize, const char* RGBA);
|
||||
id createAttributedStringFromStyledLabel(JsonNode *styledLabel, const char* fontName, int fontSize);
|
||||
|
||||
#endif //ASSETS_C_MENU_DARWIN_H
|
||||
|
||||
@@ -42,6 +42,8 @@ TrayMenu* NewTrayMenu(const char* menuJSON) {
|
||||
result->disabled = false;
|
||||
getJSONBool(processedJSON, "Disabled", &result->disabled);
|
||||
|
||||
result->styledLabel = getJSONObject(processedJSON, "StyledLabel");
|
||||
|
||||
// Create the menu
|
||||
JsonNode* processedMenu = mustJSONObject(processedJSON, "ProcessedMenu");
|
||||
result->menu = NewMenu(processedMenu);
|
||||
@@ -63,7 +65,7 @@ void DumpTrayMenu(TrayMenu* trayMenu) {
|
||||
}
|
||||
|
||||
|
||||
void UpdateTrayLabel(TrayMenu *trayMenu, const char *label, const char *fontName, int fontSize, const char *RGBA, const char *tooltip, bool disabled) {
|
||||
void UpdateTrayLabel(TrayMenu *trayMenu, const char *label, const char *fontName, int fontSize, const char *RGBA, const char *tooltip, bool disabled, JsonNode *styledLabel) {
|
||||
|
||||
// Exit early if NULL
|
||||
if( trayMenu->label == NULL ) {
|
||||
@@ -71,7 +73,12 @@ void UpdateTrayLabel(TrayMenu *trayMenu, const char *label, const char *fontName
|
||||
}
|
||||
// Update button label
|
||||
id statusBarButton = msg_reg(trayMenu->statusbaritem, s("button"));
|
||||
id attributedString = createAttributedString(label, fontName, fontSize, RGBA);
|
||||
id attributedString = NULL;
|
||||
if( styledLabel != NULL) {
|
||||
attributedString = createAttributedStringFromStyledLabel(styledLabel, fontName, fontSize);
|
||||
} else {
|
||||
attributedString = createAttributedString(label, fontName, fontSize, RGBA);
|
||||
}
|
||||
|
||||
if( tooltip != NULL ) {
|
||||
msg_id(statusBarButton, s("setToolTip:"), str(tooltip));
|
||||
@@ -125,7 +132,7 @@ void ShowTrayMenu(TrayMenu* trayMenu) {
|
||||
UpdateTrayIcon(trayMenu);
|
||||
|
||||
// Update the label if needed
|
||||
UpdateTrayLabel(trayMenu, trayMenu->label, trayMenu->fontName, trayMenu->fontSize, trayMenu->RGBA, trayMenu->tooltip, trayMenu->disabled);
|
||||
UpdateTrayLabel(trayMenu, trayMenu->label, trayMenu->fontName, trayMenu->fontSize, trayMenu->RGBA, trayMenu->tooltip, trayMenu->disabled, trayMenu->styledLabel);
|
||||
|
||||
// Update the menu
|
||||
id menu = GetMenu(trayMenu->menu);
|
||||
@@ -161,6 +168,7 @@ void UpdateTrayMenuInPlace(TrayMenu* currentMenu, TrayMenu* newMenu) {
|
||||
// Copy the other data
|
||||
currentMenu->ID = newMenu->ID;
|
||||
currentMenu->label = newMenu->label;
|
||||
currentMenu->styledLabel = newMenu->styledLabel;
|
||||
currentMenu->trayIconPosition = newMenu->trayIconPosition;
|
||||
currentMenu->icon = newMenu->icon;
|
||||
|
||||
@@ -220,7 +228,7 @@ void LoadTrayIcons() {
|
||||
int length = atoi((const char *)lengthAsString);
|
||||
|
||||
// Create the icon and add to the hashmap
|
||||
id imageData = ((id(*)(id, SEL, id, int))objc_msgSend)(c("NSData"), s("dataWithBytes:length:"), data, length);
|
||||
id imageData = ((id(*)(id, SEL, id, int))objc_msgSend)(c("NSData"), s("dataWithBytes:length:"), (id)data, length);
|
||||
id trayImage = ALLOC("NSImage");
|
||||
msg_id(trayImage, s("initWithData:"), imageData);
|
||||
hashmap_put(&trayIconCache, (const char *)name, strlen((const char *)name), trayImage);
|
||||
|
||||
@@ -29,6 +29,8 @@ typedef struct {
|
||||
|
||||
JsonNode* processedJSON;
|
||||
|
||||
JsonNode* styledLabel;
|
||||
|
||||
id delegate;
|
||||
|
||||
} TrayMenu;
|
||||
@@ -38,7 +40,7 @@ void DumpTrayMenu(TrayMenu* trayMenu);
|
||||
void ShowTrayMenu(TrayMenu* trayMenu);
|
||||
void UpdateTrayMenuInPlace(TrayMenu* currentMenu, TrayMenu* newMenu);
|
||||
void UpdateTrayIcon(TrayMenu *trayMenu);
|
||||
void UpdateTrayLabel(TrayMenu *trayMenu, const char *label, const char *fontName, int fontSize, const char *RGBA, const char *tooltip, bool disabled);
|
||||
void UpdateTrayLabel(TrayMenu *trayMenu, const char *label, const char *fontName, int fontSize, const char *RGBA, const char *tooltip, bool disabled, JsonNode *styledLabel);
|
||||
|
||||
void LoadTrayIcons();
|
||||
void UnloadTrayIcons();
|
||||
|
||||
@@ -127,7 +127,9 @@ void UpdateTrayMenuLabelInStore(TrayMenuStore* store, const char* JSON) {
|
||||
bool disabled = false;
|
||||
getJSONBool(parsedUpdate, "Disabled", &disabled);
|
||||
|
||||
UpdateTrayLabel(menu, Label, fontName, fontSize, RGBA, tooltip, disabled);
|
||||
JsonNode *styledLabel = getJSONObject(parsedUpdate, "StyledLabel");
|
||||
|
||||
UpdateTrayLabel(menu, Label, fontName, fontSize, RGBA, tooltip, disabled, styledLabel);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ package menumanager
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/leaanthony/go-ansi-parser"
|
||||
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu/keys"
|
||||
@@ -41,11 +44,25 @@ type ProcessedMenuItem struct {
|
||||
|
||||
// Tooltip
|
||||
Tooltip string `json:",omitempty"`
|
||||
|
||||
// Styled label
|
||||
StyledLabel []*ansi.StyledText `json:",omitempty"`
|
||||
}
|
||||
|
||||
func NewProcessedMenuItem(menuItemMap *MenuItemMap, menuItem *menu.MenuItem) *ProcessedMenuItem {
|
||||
|
||||
ID := menuItemMap.menuItemToIDMap[menuItem]
|
||||
|
||||
// Parse ANSI text
|
||||
var styledLabel []*ansi.StyledText
|
||||
tempLabel := menuItem.Label
|
||||
if strings.Contains(tempLabel, "\033[") {
|
||||
parsedLabel, err := ansi.Parse(menuItem.Label)
|
||||
if err == nil {
|
||||
styledLabel = parsedLabel
|
||||
}
|
||||
}
|
||||
|
||||
result := &ProcessedMenuItem{
|
||||
ID: ID,
|
||||
Label: menuItem.Label,
|
||||
@@ -63,6 +80,7 @@ func NewProcessedMenuItem(menuItemMap *MenuItemMap, menuItem *menu.MenuItem) *Pr
|
||||
MacTemplateImage: menuItem.MacTemplateImage,
|
||||
MacAlternate: menuItem.MacAlternate,
|
||||
Tooltip: menuItem.Tooltip,
|
||||
StyledLabel: styledLabel,
|
||||
}
|
||||
|
||||
if menuItem.SubMenu != nil {
|
||||
|
||||
@@ -4,8 +4,11 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/leaanthony/go-ansi-parser"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
)
|
||||
@@ -36,6 +39,7 @@ type TrayMenu struct {
|
||||
menu *menu.Menu
|
||||
ProcessedMenu *WailsMenu
|
||||
trayMenu *menu.TrayMenu
|
||||
StyledLabel []*ansi.StyledText `json:",omitempty"`
|
||||
}
|
||||
|
||||
func (t *TrayMenu) AsJSON() (string, error) {
|
||||
@@ -48,6 +52,16 @@ func (t *TrayMenu) AsJSON() (string, error) {
|
||||
|
||||
func NewTrayMenu(trayMenu *menu.TrayMenu) *TrayMenu {
|
||||
|
||||
// Parse ANSI text
|
||||
var styledLabel []*ansi.StyledText
|
||||
tempLabel := trayMenu.Label
|
||||
if strings.Contains(tempLabel, "\033[") {
|
||||
parsedLabel, err := ansi.Parse(tempLabel)
|
||||
if err == nil {
|
||||
styledLabel = parsedLabel
|
||||
}
|
||||
}
|
||||
|
||||
result := &TrayMenu{
|
||||
Label: trayMenu.Label,
|
||||
FontName: trayMenu.FontName,
|
||||
@@ -60,6 +74,7 @@ func NewTrayMenu(trayMenu *menu.TrayMenu) *TrayMenu {
|
||||
RGBA: trayMenu.RGBA,
|
||||
menuItemMap: NewMenuItemMap(),
|
||||
trayMenu: trayMenu,
|
||||
StyledLabel: styledLabel,
|
||||
}
|
||||
|
||||
result.menuItemMap.AddMenu(trayMenu.Menu)
|
||||
@@ -150,14 +165,25 @@ func (m *Manager) UpdateTrayMenuLabel(trayMenu *menu.TrayMenu) (string, error) {
|
||||
|
||||
type LabelUpdate struct {
|
||||
ID string
|
||||
Label string
|
||||
FontName string
|
||||
Label string `json:",omitempty"`
|
||||
FontName string `json:",omitempty"`
|
||||
FontSize int
|
||||
RGBA string
|
||||
RGBA string `json:",omitempty"`
|
||||
Disabled bool
|
||||
Tooltip string
|
||||
Image string
|
||||
Tooltip string `json:",omitempty"`
|
||||
Image string `json:",omitempty"`
|
||||
MacTemplateImage bool
|
||||
StyledLabel []*ansi.StyledText `json:",omitempty"`
|
||||
}
|
||||
|
||||
// Parse ANSI text
|
||||
var styledLabel []*ansi.StyledText
|
||||
tempLabel := trayMenu.Label
|
||||
if strings.Contains(tempLabel, "\033[") {
|
||||
parsedLabel, err := ansi.Parse(tempLabel)
|
||||
if err == nil {
|
||||
styledLabel = parsedLabel
|
||||
}
|
||||
}
|
||||
|
||||
update := &LabelUpdate{
|
||||
@@ -170,6 +196,7 @@ func (m *Manager) UpdateTrayMenuLabel(trayMenu *menu.TrayMenu) (string, error) {
|
||||
Image: trayMenu.Image,
|
||||
MacTemplateImage: trayMenu.MacTemplateImage,
|
||||
RGBA: trayMenu.RGBA,
|
||||
StyledLabel: styledLabel,
|
||||
}
|
||||
|
||||
data, err := json.Marshal(update)
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "Angular",
|
||||
"shortname": "angular",
|
||||
"author": "bh90210 <ktc@pm.me>",
|
||||
"description": "Angular projects w/ @angular/cli - Note: in order to reach the cli use npx like this: npx ng"
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "React JS",
|
||||
"shortname": "react",
|
||||
"author": "bh90210 <ktc@pm.me>",
|
||||
"description": "Create React App v3 standar tooling"
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
)
|
||||
|
||||
// Basic application struct
|
||||
type Basic struct {
|
||||
runtime *wails.Runtime
|
||||
}
|
||||
|
||||
// newBasic creates a new Basic application struct
|
||||
func newBasic() *Basic {
|
||||
return &Basic{}
|
||||
}
|
||||
|
||||
// WailsInit is called at application startup
|
||||
func (b *Basic) WailsInit(runtime *wails.Runtime) error {
|
||||
// Perform your setup here
|
||||
b.runtime = runtime
|
||||
runtime.Window.SetTitle("{{.ProjectName}}")
|
||||
return nil
|
||||
}
|
||||
|
||||
// WailsShutdown is called at application termination
|
||||
func (b *Basic) WailsShutdown() {
|
||||
// Perform your teardown here
|
||||
}
|
||||
|
||||
// Greet returns a greeting for the given name
|
||||
func (b *Basic) Greet(name string) string {
|
||||
return fmt.Sprintf("Hello %s!", name)
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/node_modules/
|
||||
/public/build/
|
||||
|
||||
.DS_Store
|
||||
@@ -1,93 +0,0 @@
|
||||
*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
|
||||
|
||||
---
|
||||
|
||||
# svelte app
|
||||
|
||||
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
|
||||
|
||||
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
|
||||
|
||||
```bash
|
||||
npx degit sveltejs/template svelte-app
|
||||
cd svelte-app
|
||||
```
|
||||
|
||||
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
|
||||
|
||||
|
||||
## Get started
|
||||
|
||||
Install the dependencies...
|
||||
|
||||
```bash
|
||||
cd svelte-app
|
||||
npm install
|
||||
```
|
||||
|
||||
...then start [Rollup](https://rollupjs.org):
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
|
||||
|
||||
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
|
||||
|
||||
|
||||
## Building and running in production mode
|
||||
|
||||
To create an optimised version of the app:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
|
||||
|
||||
|
||||
## Single-page app mode
|
||||
|
||||
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
|
||||
|
||||
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
|
||||
|
||||
```js
|
||||
"start": "sirv public --single"
|
||||
```
|
||||
|
||||
|
||||
## Deploying to the web
|
||||
|
||||
### With [now](https://zeit.co/now)
|
||||
|
||||
Install `now` if you haven't already:
|
||||
|
||||
```bash
|
||||
npm install -g now
|
||||
```
|
||||
|
||||
Then, from within your project folder:
|
||||
|
||||
```bash
|
||||
cd public
|
||||
now deploy --name my-project
|
||||
```
|
||||
|
||||
As an alternative, use the [Now desktop client](https://zeit.co/download) and simply drag the unzipped project folder to the taskbar icon.
|
||||
|
||||
### With [surge](https://surge.sh/)
|
||||
|
||||
Install `surge` if you haven't already:
|
||||
|
||||
```bash
|
||||
npm install -g surge
|
||||
```
|
||||
|
||||
Then, from within your project folder:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
surge public my-project.surge.sh
|
||||
```
|
||||
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"name": "svelte-app",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"build": "npx rollup -c",
|
||||
"dev": "npx rollup -c -w",
|
||||
"start": "npx sirv public",
|
||||
"start:dev": "npx sirv public --single --host 0.0.0.0 --dev"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
"@rollup/plugin-node-resolve": "^11.0.1",
|
||||
"focus-visible": "^5.2.0",
|
||||
"rollup": "^2.35.1",
|
||||
"rollup-plugin-livereload": "^2.0.0",
|
||||
"rollup-plugin-svelte": "^7.0.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"svelte": "^3.31.1",
|
||||
"svelte-mui": "^0.3.3-5"
|
||||
},
|
||||
"dependencies": {
|
||||
"sirv-cli": "^0.4.4"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.9 KiB |
@@ -1,24 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
<meta name="apple-mobile-web-app-title" content="svelte-mui" />
|
||||
<meta name="application-name" content="svelte-mui" />
|
||||
<meta name="theme-color" content="#212121" />
|
||||
|
||||
<title>Svelte app</title>
|
||||
|
||||
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||
<link rel='stylesheet' href='/bundle.css'>
|
||||
|
||||
<script defer src='/bundle.js'></script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>Please enable JavaScript.</noscript>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,71 +0,0 @@
|
||||
import svelte from 'rollup-plugin-svelte';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import livereload from 'rollup-plugin-livereload';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
|
||||
const production = !process.env.ROLLUP_WATCH;
|
||||
|
||||
export default {
|
||||
input: 'src/main.js',
|
||||
output: {
|
||||
sourcemap: true,
|
||||
format: 'iife',
|
||||
name: 'app',
|
||||
file: 'public/bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
svelte({
|
||||
// enable run-time checks when not in production
|
||||
dev: !production,
|
||||
// we'll extract any component CSS out into
|
||||
// a separate file - better for performance
|
||||
css: css => {
|
||||
css.write('public/bundle.css');
|
||||
}
|
||||
}),
|
||||
|
||||
// If you have external dependencies installed from
|
||||
// npm, you'll most likely need these plugins. In
|
||||
// some cases you'll need additional configuration -
|
||||
// consult the documentation for details:
|
||||
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
||||
resolve({
|
||||
browser: true,
|
||||
dedupe: ['svelte']
|
||||
}),
|
||||
commonjs(),
|
||||
|
||||
// In dev mode, call `npm run start` once
|
||||
// the bundle has been generated
|
||||
!production && serve(),
|
||||
|
||||
// Watch the `public` directory and refresh the
|
||||
// browser on changes when not in production
|
||||
!production && livereload('public'),
|
||||
|
||||
// If we're building for production (npm run build
|
||||
// instead of npm run dev), minify
|
||||
production && terser()
|
||||
],
|
||||
watch: {
|
||||
clearScreen: false
|
||||
}
|
||||
};
|
||||
|
||||
function serve() {
|
||||
let started = false;
|
||||
|
||||
return {
|
||||
writeBundle() {
|
||||
if (!started) {
|
||||
started = true;
|
||||
|
||||
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
|
||||
stdio: ['ignore', 'inherit', 'inherit'],
|
||||
shell: true
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
<h1>Hello {name}!</h1>
|
||||
|
||||
<Snackbar bind:visible bg="#f44336">
|
||||
{response}
|
||||
<span slot="action">
|
||||
<Button color="#ff0" on:click={() => (visible = false)}>Close</Button>
|
||||
</span>
|
||||
</Snackbar>
|
||||
|
||||
<Textfield
|
||||
autocomplete="off"
|
||||
label="Message"
|
||||
required
|
||||
bind:value
|
||||
message=""
|
||||
/>
|
||||
|
||||
<Button
|
||||
outlined
|
||||
shaped
|
||||
color="Red"
|
||||
on:click={() => {
|
||||
window.backend.main.Basic.Greet(value).then((result) => {
|
||||
response = result;
|
||||
visible = true;
|
||||
});
|
||||
}}
|
||||
>
|
||||
Hello
|
||||
</Button>
|
||||
|
||||
|
||||
<script>
|
||||
export let name;
|
||||
let value = '';
|
||||
let response = '';
|
||||
|
||||
// optional import focus-visible polyfill only once
|
||||
import 'focus-visible';
|
||||
// import any components
|
||||
import { Button, Checkbox, Snackbar, Textfield } from 'svelte-mui';
|
||||
|
||||
let checked = true;
|
||||
let visible = false;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
color: purple;
|
||||
}
|
||||
</style>
|
||||
@@ -1,10 +0,0 @@
|
||||
import App from './App.svelte';
|
||||
|
||||
const app = new App({
|
||||
target: document.body,
|
||||
props: {
|
||||
name: 'Wails User'
|
||||
}
|
||||
});
|
||||
|
||||
export default app;
|
||||
@@ -1,9 +0,0 @@
|
||||
module test
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/wailsapp/wails/v2 v2.0.0-alpha
|
||||
)
|
||||
|
||||
replace github.com/wailsapp/wails/v2 v2.0.0-alpha => {{.WailsDirectory}}
|
||||
@@ -1,22 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// Create application with options
|
||||
app, err := wails.CreateApp("{{.ProjectName}}", 1024, 768)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
app.Bind(newBasic())
|
||||
|
||||
err = app.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "Svelte + MUI3",
|
||||
"shortname": "svelte-mui",
|
||||
"author": "Travis McLane <travis.mclane@gmail.com>",
|
||||
"description": "A simple template using Svelte + Mui3",
|
||||
"helpurl": "https://wails.app/help/templates/svelte-mui3"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"name": "{{.ProjectName}}",
|
||||
"outputfilename": "{{.BinaryName}}",
|
||||
"html": "frontend/public/index.html",
|
||||
"js": "frontend/public/bundle.js",
|
||||
"css": "frontend/public/bundle.css",
|
||||
"frontend:build": "npm run build",
|
||||
"frontend:install": "npm install"
|
||||
}
|
||||
@@ -23,6 +23,7 @@ button {
|
||||
border-radius: 3px;
|
||||
outline: none;
|
||||
height: 20px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
#logo {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// Get input + focus
|
||||
var nameElement = document.getElementById("name");
|
||||
let nameElement = document.getElementById("name");
|
||||
nameElement.focus();
|
||||
|
||||
// Stup the greet function
|
||||
// Setup the greet function
|
||||
window.greet = function () {
|
||||
|
||||
// Get name
|
||||
var name = nameElement.value;
|
||||
let name = nameElement.value;
|
||||
|
||||
// Call Basic.Greet(name)
|
||||
window.backend.main.Basic.Greet(name).then((result) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module test
|
||||
|
||||
go 1.13
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/wailsapp/wails/v2 v2.0.0-alpha
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "Vue2/Webpack Basic",
|
||||
"shortname": "vue",
|
||||
"author": "Lea Anthony<lea.anthony@gmail.com>",
|
||||
"description": "A basic template using Vue 2 and bundled using Webpack 4"
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "Vuetify1.5/Webpack Basic",
|
||||
"shortname": "vuetify1",
|
||||
"author": "Lea Anthony <lea.anthony@gmail.com>",
|
||||
"description": "Basic template using Vuetify v1.5 and bundled using Webpack"
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
)
|
||||
|
||||
// Basic application struct
|
||||
type Basic struct {
|
||||
runtime *wails.Runtime
|
||||
}
|
||||
|
||||
// newBasic creates a new Basic application struct
|
||||
func newBasic() *Basic {
|
||||
return &Basic{}
|
||||
}
|
||||
|
||||
// WailsInit is called at application startup
|
||||
func (b *Basic) WailsInit(runtime *wails.Runtime) error {
|
||||
// Perform your setup here
|
||||
b.runtime = runtime
|
||||
runtime.Window.SetTitle("{{.ProjectName}}")
|
||||
return nil
|
||||
}
|
||||
|
||||
// WailsShutdown is called at application termination
|
||||
func (b *Basic) WailsShutdown() {
|
||||
// Perform your teardown here
|
||||
}
|
||||
|
||||
// Greet returns a greeting for the given name
|
||||
func (b *Basic) Greet(name string) string {
|
||||
return fmt.Sprintf("Hello %s!", name)
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
[ '@vue/app', { useBuiltIns: 'entry' } ]
|
||||
]
|
||||
};
|
||||
@@ -1,52 +0,0 @@
|
||||
{
|
||||
"name": "vuetify2",
|
||||
"author": "{{.AuthorNameAndEmail}}",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.6.1",
|
||||
"regenerator-runtime": "^0.13.3",
|
||||
"vue": "^2.5.22",
|
||||
"vuetify": "^2.2.17"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mdi/font": "^4.3.95",
|
||||
"@vue/cli-plugin-babel": "^3.4.0",
|
||||
"@vue/cli-plugin-eslint": "^3.4.0",
|
||||
"@vue/cli-service": "^3.4.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"eslint": "^5.8.0",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"eventsource-polyfill": "^0.9.6",
|
||||
"vue-template-compiler": "^2.5.21",
|
||||
"webpack-hot-middleware": "^2.24.3"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/essential",
|
||||
"eslint:recommended"
|
||||
],
|
||||
"rules": {},
|
||||
"parserOptions": {
|
||||
"parser": "babel-eslint"
|
||||
}
|
||||
},
|
||||
"postcss": {
|
||||
"plugins": {
|
||||
"autoprefixer": {}
|
||||
}
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not ie <= 8"
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><title>Wails</title></head><body><div id=app></div></body></html>
|
||||
@@ -1,60 +0,0 @@
|
||||
<template>
|
||||
<v-app id="inspire">
|
||||
<v-navigation-drawer v-model="drawer" clipped fixed app>
|
||||
<v-list dense>
|
||||
<v-list-item>
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-view-dashboard</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>Dashboard</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-list-item>
|
||||
<v-list-item-icon>
|
||||
<v-icon>mdi-settings</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>Settings</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
<v-app-bar app fixed clipped-left>
|
||||
<v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
|
||||
<v-toolbar-title>Application</v-toolbar-title>
|
||||
</v-app-bar>
|
||||
<v-content>
|
||||
<v-container fluid class="px-0">
|
||||
<v-layout justify-center align-center class="px-0">
|
||||
<hello-world></hello-world>
|
||||
</v-layout>
|
||||
</v-container>
|
||||
</v-content>
|
||||
<v-footer app fixed>
|
||||
<span style="margin-left:1em">© You</span>
|
||||
</v-footer>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HelloWorld from "./components/HelloWorld.vue"
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
drawer: false
|
||||
}),
|
||||
components: {
|
||||
HelloWorld
|
||||
},
|
||||
props: {
|
||||
source: String
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.logo {
|
||||
width: 16em;
|
||||
}
|
||||
</style>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 301 KiB |
@@ -1,85 +0,0 @@
|
||||
<template>
|
||||
<v-container fluid class="px-0">
|
||||
<v-layout>
|
||||
<v-flex xs12 sm6 offset-sm3>
|
||||
<v-card raised="raised" class="pa-4 ma-4">
|
||||
<v-layout justify-center align-center class="pa-4 ma-4">
|
||||
<v-img :src="require('../assets/images/logo.png')"></v-img>
|
||||
</v-layout>
|
||||
<v-card-actions>
|
||||
<v-layout justify-center align-center class="px-0">
|
||||
<v-btn color="blue" @click="getMessage">Press Me</v-btn>
|
||||
</v-layout>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
<div class="text-xs-center">
|
||||
<v-dialog v-model="dialog" width="500">
|
||||
<v-card>
|
||||
<v-card-title class="headline" primary-title>Message from Go</v-card-title>
|
||||
<v-card-text>{{message}}</v-card-text>
|
||||
<v-divider></v-divider>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="primary" text @click="dialog = false">Awesome</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
message: " ",
|
||||
raised: true,
|
||||
dialog: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getMessage: function () {
|
||||
var self = this
|
||||
window.backend.main.Basic.Greet("Hello from Go!").then(result => {
|
||||
self.message = result
|
||||
self.dialog = true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h1 {
|
||||
margin-top: 2em;
|
||||
position: relative;
|
||||
min-height: 5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
font-size: 1.7em;
|
||||
border-color: blue;
|
||||
background-color: blue;
|
||||
color: white;
|
||||
border: 3px solid white;
|
||||
border-radius: 10px;
|
||||
padding: 9px;
|
||||
cursor: pointer;
|
||||
transition: 500ms;
|
||||
}
|
||||
|
||||
a {
|
||||
font-size: 1.7em;
|
||||
border-color: white;
|
||||
background-color: #121212;
|
||||
color: white;
|
||||
border: 3px solid white;
|
||||
border-radius: 10px;
|
||||
padding: 9px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
@@ -1,27 +0,0 @@
|
||||
import 'core-js/stable';
|
||||
import 'regenerator-runtime/runtime';
|
||||
import '@mdi/font/css/materialdesignicons.css';
|
||||
import Vue from 'vue';
|
||||
import Vuetify from 'vuetify';
|
||||
import 'vuetify/dist/vuetify.min.css';
|
||||
|
||||
Vue.use(Vuetify);
|
||||
|
||||
import App from './App.vue';
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
Vue.config.devtools = true;
|
||||
|
||||
Wails.Init(() => {
|
||||
new Vue({
|
||||
vuetify: new Vuetify({
|
||||
icons: {
|
||||
iconfont: 'mdi'
|
||||
},
|
||||
theme: {
|
||||
dark: true
|
||||
}
|
||||
}),
|
||||
render: h => h(App)
|
||||
}).$mount('#app');
|
||||
});
|
||||
@@ -1,60 +0,0 @@
|
||||
let cssConfig = {};
|
||||
|
||||
if (process.env.NODE_ENV == 'production') {
|
||||
cssConfig = {
|
||||
extract: {
|
||||
filename: '[name].css',
|
||||
chunkFilename: '[name].css'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
indexPath: 'index.html',
|
||||
publicPath: 'public',
|
||||
// disable hashes in filenames
|
||||
filenameHashing: false,
|
||||
// delete HTML related webpack plugins
|
||||
chainWebpack: config => {
|
||||
config.plugins.delete('preload');
|
||||
config.plugins.delete('prefetch');
|
||||
config
|
||||
.plugin('html')
|
||||
.tap(args => {
|
||||
args[0].template = 'public/index.html';
|
||||
args[0].inject = false;
|
||||
args[0].cache = false;
|
||||
args[0].minify = false;
|
||||
args[0].filename = 'index.html';
|
||||
return args;
|
||||
});
|
||||
|
||||
let limit = 9999999999999999;
|
||||
config.module
|
||||
.rule('images')
|
||||
.test(/\.(png|gif|jpg)(\?.*)?$/i)
|
||||
.use('url-loader')
|
||||
.loader('url-loader')
|
||||
.tap(options => Object.assign(options, { limit: limit }));
|
||||
config.module
|
||||
.rule('fonts')
|
||||
.test(/\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/i)
|
||||
.use('url-loader')
|
||||
.loader('url-loader')
|
||||
.options({
|
||||
limit: limit
|
||||
});
|
||||
},
|
||||
css: cssConfig,
|
||||
configureWebpack: {
|
||||
output: {
|
||||
filename: '[name].js'
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: false
|
||||
}
|
||||
},
|
||||
devServer: {
|
||||
disableHostCheck: true
|
||||
}
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
module test
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/wailsapp/wails/v2 v2.0.0-alpha
|
||||
)
|
||||
|
||||
replace github.com/wailsapp/wails/v2 v2.0.0-alpha => {{.WailsDirectory}}
|
||||
@@ -1,15 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// Create application with options
|
||||
app := wails.CreateApp("{{.ProjectName}}", 1024, 768)
|
||||
|
||||
app.Bind(newBasic())
|
||||
|
||||
app.Run()
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "Vuetify 2 ",
|
||||
"shortname": "vuetify2",
|
||||
"author": "Michael Hipp <michael@redmule.com>",
|
||||
"description": "A simple template using only HTML/CSS/JS",
|
||||
"helpurl": "https://wails.app/help/templates/vuetify2"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"name": "{{.ProjectName}}",
|
||||
"outputfilename": "{{.BinaryName}}",
|
||||
"html": "frontend/dist/index.html",
|
||||
"js": "frontend/dist/app.js",
|
||||
"css": "frontend/dist/app.css",
|
||||
"frontend:build": "npm run build",
|
||||
"frontend:install": "npm install",
|
||||
"author": {
|
||||
"name": "{{.AuthorName}}",
|
||||
"email": "{{.AuthorEmail}}"
|
||||
}
|
||||
}
|
||||
@@ -190,10 +190,11 @@ func (b *BaseBuilder) CompileProject(options *Options) error {
|
||||
|
||||
var tags slicer.StringSlicer
|
||||
tags.Add(options.OutputType)
|
||||
|
||||
tags.AddSlice(options.UserTags)
|
||||
if options.Mode == Debug {
|
||||
tags.Add("debug")
|
||||
}
|
||||
tags.Deduplicate()
|
||||
|
||||
// Add the output type build tag
|
||||
commands.Add("-tags")
|
||||
|
||||
@@ -29,6 +29,7 @@ var modeMap = []string{"Debug", "Production"}
|
||||
// Options contains all the build options as well as the project data
|
||||
type Options struct {
|
||||
LDFlags string // Optional flags to pass to linker
|
||||
UserTags []string // Tags to pass to the Go compiler
|
||||
Logger *clilogger.CLILogger // All output to the logger
|
||||
OutputType string // EG: desktop, server....
|
||||
Mode Mode // release or debug
|
||||
|
||||
@@ -49,4 +49,4 @@ Example:
|
||||
|
||||
## Mac
|
||||
|
||||
The `mac` directory holds files specific to Mac builds, such as `info.plist`. These may be edited and used as part of the build.
|
||||
The `mac` directory holds files specific to Mac builds, such as `Info.plist`. These may be edited and used as part of the build.
|
||||
|
||||
@@ -42,7 +42,7 @@ func packageApplication(options *Options) error {
|
||||
return errors.Wrap(err, "Cannot move file: "+options.ProjectData.OutputFilename)
|
||||
}
|
||||
|
||||
// Generate info.plist
|
||||
// Generate Info.plist
|
||||
err = processPList(options, contentsDirectory)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -68,7 +68,7 @@ func packageApplication(options *Options) error {
|
||||
func processPList(options *Options, contentsDirectory string) error {
|
||||
|
||||
// Check if plist already exists in project dir
|
||||
plistFile := filepath.Join(options.ProjectData.AssetsDir, "mac", "info.plist")
|
||||
plistFile := filepath.Join(options.ProjectData.AssetsDir, "mac", "Info.plist")
|
||||
|
||||
// If the file doesn't exist, generate it
|
||||
if !fs.FileExists(plistFile) {
|
||||
@@ -79,7 +79,7 @@ func processPList(options *Options, contentsDirectory string) error {
|
||||
}
|
||||
|
||||
// Copy it to the contents directory
|
||||
targetFile := filepath.Join(contentsDirectory, "info.plist")
|
||||
targetFile := filepath.Join(contentsDirectory, "Info.plist")
|
||||
return fs.CopyFile(plistFile, targetFile)
|
||||
}
|
||||
|
||||
@@ -88,11 +88,11 @@ func generateDefaultPlist(options *Options, targetPlistFile string) error {
|
||||
exe := defaultString(options.OutputFile, name)
|
||||
version := "1.0.0"
|
||||
author := defaultString(options.ProjectData.Author.Name, "Anonymous")
|
||||
packageID := strings.Join([]string{"wails", name, version}, ".")
|
||||
packageID := strings.Join([]string{"wails", name}, ".")
|
||||
plistData := newPlistData(name, exe, packageID, version, author)
|
||||
|
||||
tmpl := template.New("infoPlist")
|
||||
plistTemplate := fs.RelativePath("./internal/packager/darwin/info.plist")
|
||||
plistTemplate := fs.RelativePath("./internal/packager/darwin/Info.plist")
|
||||
infoPlist, err := ioutil.ReadFile(plistTemplate)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Cannot open plist template")
|
||||
|
||||
30
v2/pkg/mac/notification_darwin.go
Normal file
30
v2/pkg/mac/notification_darwin.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// Package mac provides MacOS related utility functions for Wails applications
|
||||
package mac
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/wailsapp/wails/v2/internal/shell"
|
||||
)
|
||||
|
||||
// StartAtLogin will either add or remove this application to/from the login
|
||||
// items, depending on the given boolean flag. The limitation is that the
|
||||
// currently running app must be in an app bundle.
|
||||
func ShowNotification(title string, subtitle string, message string, sound string) error {
|
||||
command := fmt.Sprintf("display notification \"%s\"", message)
|
||||
if len(title) > 0 {
|
||||
command += fmt.Sprintf(" with title \"%s\"", title)
|
||||
}
|
||||
if len(subtitle) > 0 {
|
||||
command += fmt.Sprintf(" subtitle \"%s\"", subtitle)
|
||||
}
|
||||
if len(sound) > 0 {
|
||||
command += fmt.Sprintf(" sound name \"%s\"", sound)
|
||||
}
|
||||
_, stde, err := shell.RunCommand("/tmp", "osascript", "-e", command)
|
||||
if err != nil {
|
||||
errors.Wrap(err, stde)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
34
v2/pkg/mac/notification_darwin_test.go
Normal file
34
v2/pkg/mac/notification_darwin_test.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package mac
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestShowNotification(t *testing.T) {
|
||||
type args struct {
|
||||
title string
|
||||
subtitle string
|
||||
message string
|
||||
sound string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
title string
|
||||
subtitle string
|
||||
message string
|
||||
sound string
|
||||
wantErr bool
|
||||
}{
|
||||
{"No message", "", "", "", "", false},
|
||||
{"Title only", "I am a Title", "", "", "", false},
|
||||
{"SubTitle only", "", "I am a subtitle", "", "", false},
|
||||
{"Message only", "", "", "I am a message!", "", false},
|
||||
{"Sound only", "", "", "", "submarine.aiff", false},
|
||||
{"Full", "Title", "Subtitle", "This is a long message to show that text gets wrapped in a notification", "submarine.aiff", false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := ShowNotification(tt.title, tt.subtitle, tt.message, tt.sound); (err != nil) != tt.wantErr {
|
||||
t.Errorf("ShowNotification() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/leaanthony/slicer"
|
||||
)
|
||||
|
||||
var namedKeys = slicer.String([]string{"backspace", "tab", "return", "escape", "left", "right", "up", "down", "space", "delete", "home", "end", "page up", "page down", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "f32", "f33", "f34", "f35", "numlock"})
|
||||
var namedKeys = slicer.String([]string{"backspace", "tab", "return", "enter", "escape", "left", "right", "up", "down", "space", "delete", "home", "end", "page up", "page down", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "f32", "f33", "f34", "f35", "numlock"})
|
||||
|
||||
func parseKey(key string) (string, bool) {
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"go/ast"
|
||||
"strings"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/fatih/structtag"
|
||||
)
|
||||
|
||||
@@ -225,7 +224,6 @@ func (p *Parser) parseField(file *ast.File, field *ast.Field, pkg *Package) ([]*
|
||||
}
|
||||
|
||||
default:
|
||||
spew.Dump(t)
|
||||
return nil, fmt.Errorf("unsupported field found in struct: %+v", t)
|
||||
}
|
||||
|
||||
|
||||
2
v2/test/kitchensink/.gitignore
vendored
2
v2/test/kitchensink/.gitignore
vendored
@@ -1 +1 @@
|
||||
info.plist
|
||||
Info.plist
|
||||
Reference in New Issue
Block a user