5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 15:42:53 +08:00

Support logging

This commit is contained in:
Lea Anthony 2023-02-06 20:29:33 +11:00
parent 3bd6c34ae6
commit f94e798c50
No known key found for this signature in database
GPG Key ID: 33DAF7BB90A58405
22 changed files with 339 additions and 105 deletions

View File

@ -32,6 +32,10 @@ Similarly, the `Emit` function has changed. Instead of taking a name and optiona
In v2, `Off` and `OffAll` calls would remove events in both JS and Go. Due to the multi-window nature of v3, this has been changed so that these methods only apply to the context they are called in. For example, if you call `Off` in a window, it will only remove events for that window. If you use `Off` in Go, it will only remove events for Go.
### Logging
There was a lot of requests for different types of logging in v2 so for v3 we have simplified things to make it as customisable as you want. There is now a single call `Log` that takes a LogMessage object. This object contains the message, the level, and the source, the log message and any data to be printed out. The default logger is the Console logger, however any number of outputs to log to can be added. Simply add custom loggers to the `options.Application.Logger.CustomLoggers` slice. The default logger does not have log level filtering, however custom loggers can be added that do.
### Developer notes
When emitting an event in Go, it will dispatch the event to local Go listeners and also each window in the application.
@ -39,11 +43,11 @@ When emitting an event in JS, it now sends the event to the application. This wi
## Window
TBD
The Window API has largely remained the same, however there are a few changes to note.
## ClipBoard
TBD
The clipboard API has been simplified. There is now a single `Clipboard` object that can be used to read and write to the clipboard. The `Clipboard` object is available in both Go and JS. `SetText()` to set the text and `Text()` to get the text.
## Bindings
@ -51,3 +55,5 @@ TBD
## Dialogs
Dialogs are now available in JavaScript!

View File

@ -37,6 +37,6 @@ func GenerateBindings(options *GenerateBindingsOptions) error {
if err != nil {
return fmt.Errorf("error writing models file: %v", err)
}
println("Generated models file '" + options.ModelsFilename + "'")
return nil
}

View File

@ -183,5 +183,5 @@ export function OffAll() {
Emit emits an event to all listeners
*/
export function Emit(event) {
call("Emit", event);
return call("Emit", event);
}

View File

@ -0,0 +1,23 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
/* jshint esversion: 9 */
import {newRuntimeCaller} from "./runtime";
let call = newRuntimeCaller("log");
/**
* Logs a message.
* @param {message} Message to log
*/
export function Log(message) {
return call("Log", message);
}

View File

@ -13,6 +13,7 @@ import {dialogCallback, dialogErrorCallback, Error, Info, OpenFile, Question, Sa
import * as Clipboard from './clipboard';
import * as Application from './application';
import * as Log from './log';
import {newWindow} from "./window";
import {dispatchCustomEvent, Emit, Off, OffAll, On, Once, OnMultiple} from "./events";
@ -37,6 +38,7 @@ export function newRuntime(id) {
Application: {
...Application
},
Log,
Dialog: {
Info,
Warning,

View File

@ -15,7 +15,9 @@ const runtimeURL = window.location.origin + "/wails/runtime";
function runtimeCall(method, args) {
let url = new URL(runtimeURL);
url.searchParams.append("method", method);
url.searchParams.append("args", JSON.stringify(args));
if(args) {
url.searchParams.append("args", JSON.stringify(args));
}
return new Promise((resolve, reject) => {
fetch(url)
.then(response => {
@ -37,7 +39,6 @@ function runtimeCall(method, args) {
export function newRuntimeCaller(object, id) {
if (!id || id === -1) {
return function (method, args) {
args = args || {};
return runtimeCall(object + "." + method, args);
};
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
(()=>{var W=Object.defineProperty;var x=(t,e)=>{for(var n in e)W(t,n,{get:e[n],enumerable:!0})};var y=window.location.origin+"/wails/runtime";function h(t,e){let n=new URL(y);return n.searchParams.append("method",t),n.searchParams.append("args",JSON.stringify(e)),new Promise((i,r)=>{fetch(n).then(o=>{if(o.ok)return o.headers.get("content-type")&&o.headers.get("content-type").indexOf("application/json")!==-1?o.json():o.text();r(Error(o.statusText))}).then(o=>i(o)).catch(o=>r(o))})}function l(t,e){return!e||e===-1?function(n,i){return i=i||{},h(t+"."+n,i)}:function(n,i){return i=i||{},i.windowID=e,h(t+"."+n,i)}}var D="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var w=(t=21)=>{let e="",n=t;for(;n--;)e+=D[Math.random()*64|0];return e};var I=l("dialog"),u=new Map;function Q(){let t;do t=w();while(u.has(t));return t}function S(t,e,n){let i=u.get(t);i&&(n?i.resolve(JSON.parse(e)):i.resolve(e),u.delete(t))}function g(t,e){let n=u.get(t);n&&(n.reject(e),u.delete(t))}function c(t,e){return new Promise((n,i)=>{let r=Q();e=e||{},e["dialog-id"]=r,u.set(r,{resolve:n,reject:i}),I(t,e).catch(o=>{i(o),u.delete(r)})})}function C(t){return c("Info",t)}function M(t){return c("Warning",t)}function O(t){return c("Error",t)}function b(t){return c("Question",t)}function v(t){return c("OpenFile",t)}function E(t){return c("SaveFile",t)}var f={};x(f,{SetText:()=>H,Text:()=>B});var T=l("clipboard");function H(t){return T("SetText",{text:t})}function B(){return T("Text")}var p={};x(p,{Hide:()=>L,Quit:()=>J,Show:()=>N});var m=l("application");function L(){return m("Hide")}function N(){return m("Show")}function J(){return m("Quit")}function k(t){let e=l("window",t);return{Center:()=>e("Center"),SetTitle:n=>e("SetTitle",{title:n}),Fullscreen:()=>e("Fullscreen"),UnFullscreen:()=>e("UnFullscreen"),SetSize:(n,i)=>e("SetSize",{width:n,height:i}),Size:()=>e("Size"),SetMaxSize:(n,i)=>e("SetMaxSize",{width:n,height:i}),SetMinSize:(n,i)=>e("SetMinSize",{width:n,height:i}),SetAlwaysOnTop:n=>e("SetAlwaysOnTop",{alwaysOnTop:n}),SetPosition:(n,i)=>e("SetPosition",{x:n,y:i}),Position:()=>e("Position"),Screen:()=>e("Screen"),Hide:()=>e("Hide"),Maximise:()=>e("Maximise"),Show:()=>e("Show"),ToggleMaximise:()=>e("ToggleMaximise"),UnMaximise:()=>e("UnMaximise"),Minimise:()=>e("Minimise"),UnMinimise:()=>e("UnMinimise"),SetBackgroundColour:(n,i,r,o)=>e("SetBackgroundColour",{r:n,g:i,b:r,a:o})}}var G=l("events"),d=class{constructor(e,n,i){this.eventName=e,this.maxCallbacks=i||-1,this.Callback=r=>(n(r),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}};var a=new Map;function s(t,e,n){let i=a.get(t)||[],r=new d(t,e,n);return i.push(r),a.set(t,i),()=>_(r)}function R(t,e){return s(t,e,-1)}function F(t,e){return s(t,e,1)}function _(t){let e=t.eventName,n=a.get(e).filter(i=>i!==t);n.length===0?a.delete(e):a.set(e,n)}function U(t){console.log("dispatching event: ",{event:t});let e=a.get(t.name);if(e){let n=[];e.forEach(i=>{i.Callback(t)&&n.push(i)}),n.length>0&&(e=e.filter(i=>!n.includes(i)),e.length===0?a.delete(t.name):a.set(t.name,e))}}function z(t,...e){[t,...e].forEach(i=>{a.delete(i)})}function A(){a.clear()}function P(t){G("Emit",t)}window.wails={...j(-1)};window._wails={dialogCallback:S,dialogErrorCallback:g,dispatchCustomEvent:U};function j(t){return{Clipboard:{...f},Application:{...p},Dialog:{Info:C,Warning:M,Error:O,Question:b,OpenFile:v,SaveFile:E},Events:{Emit:P,On:R,Once:F,OnMultiple:s,Off:z,OffAll:A},Window:k(t)}}console.log("Wails v3.0.0 Debug Mode Enabled");})();
(()=>{var y=Object.defineProperty;var f=(t,e)=>{for(var n in e)y(t,n,{get:e[n],enumerable:!0})};var L=window.location.origin+"/wails/runtime";function h(t,e){let n=new URL(L);return n.searchParams.append("method",t),e&&n.searchParams.append("args",JSON.stringify(e)),new Promise((i,r)=>{fetch(n).then(o=>{if(o.ok)return o.headers.get("content-type")&&o.headers.get("content-type").indexOf("application/json")!==-1?o.json():o.text();r(Error(o.statusText))}).then(o=>i(o)).catch(o=>r(o))})}function l(t,e){return!e||e===-1?function(n,i){return h(t+"."+n,i)}:function(n,i){return i=i||{},i.windowID=e,h(t+"."+n,i)}}var D="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var g=(t=21)=>{let e="",n=t;for(;n--;)e+=D[Math.random()*64|0];return e};var I=l("dialog"),u=new Map;function Q(){let t;do t=g();while(u.has(t));return t}function S(t,e,n){let i=u.get(t);i&&(n?i.resolve(JSON.parse(e)):i.resolve(e),u.delete(t))}function C(t,e){let n=u.get(t);n&&(n.reject(e),u.delete(t))}function c(t,e){return new Promise((n,i)=>{let r=Q();e=e||{},e["dialog-id"]=r,u.set(r,{resolve:n,reject:i}),I(t,e).catch(o=>{i(o),u.delete(r)})})}function M(t){return c("Info",t)}function O(t){return c("Warning",t)}function b(t){return c("Error",t)}function v(t){return c("Question",t)}function E(t){return c("OpenFile",t)}function R(t){return c("SaveFile",t)}var m={};f(m,{SetText:()=>H,Text:()=>B});var T=l("clipboard");function H(t){return T("SetText",{text:t})}function B(){return T("Text")}var d={};f(d,{Hide:()=>N,Quit:()=>G,Show:()=>J});var p=l("application");function N(){return p("Hide")}function J(){return p("Show")}function G(){return p("Quit")}var x={};f(x,{Log:()=>j});var _=l("log");function j(t){return _("Log",t)}function k(t){let e=l("window",t);return{Center:()=>e("Center"),SetTitle:n=>e("SetTitle",{title:n}),Fullscreen:()=>e("Fullscreen"),UnFullscreen:()=>e("UnFullscreen"),SetSize:(n,i)=>e("SetSize",{width:n,height:i}),Size:()=>e("Size"),SetMaxSize:(n,i)=>e("SetMaxSize",{width:n,height:i}),SetMinSize:(n,i)=>e("SetMinSize",{width:n,height:i}),SetAlwaysOnTop:n=>e("SetAlwaysOnTop",{alwaysOnTop:n}),SetPosition:(n,i)=>e("SetPosition",{x:n,y:i}),Position:()=>e("Position"),Screen:()=>e("Screen"),Hide:()=>e("Hide"),Maximise:()=>e("Maximise"),Show:()=>e("Show"),ToggleMaximise:()=>e("ToggleMaximise"),UnMaximise:()=>e("UnMaximise"),Minimise:()=>e("Minimise"),UnMinimise:()=>e("UnMinimise"),SetBackgroundColour:(n,i,r,o)=>e("SetBackgroundColour",{r:n,g:i,b:r,a:o})}}var q=l("events"),w=class{constructor(e,n,i){this.eventName=e,this.maxCallbacks=i||-1,this.Callback=r=>(n(r),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}};var a=new Map;function s(t,e,n){let i=a.get(t)||[],r=new w(t,e,n);return i.push(r),a.set(t,i),()=>K(r)}function F(t,e){return s(t,e,-1)}function U(t,e){return s(t,e,1)}function K(t){let e=t.eventName,n=a.get(e).filter(i=>i!==t);n.length===0?a.delete(e):a.set(e,n)}function z(t){console.log("dispatching event: ",{event:t});let e=a.get(t.name);if(e){let n=[];e.forEach(i=>{i.Callback(t)&&n.push(i)}),n.length>0&&(e=e.filter(i=>!n.includes(i)),e.length===0?a.delete(t.name):a.set(t.name,e))}}function A(t,...e){[t,...e].forEach(i=>{a.delete(i)})}function P(){a.clear()}function W(t){return q("Emit",t)}window.wails={...V(-1)};window._wails={dialogCallback:S,dialogErrorCallback:C,dispatchCustomEvent:z};function V(t){return{Clipboard:{...m},Application:{...d},Log:x,Dialog:{Info:M,Warning:O,Error:b,Question:v,OpenFile:E,SaveFile:R},Events:{Emit:W,On:F,Once:U,OnMultiple:s,Off:A,OffAll:P},Window:k(t)}}console.log("Wails v3.0.0 Debug Mode Enabled");})();

View File

@ -1 +1 @@
(()=>{var W=Object.defineProperty;var x=(t,e)=>{for(var n in e)W(t,n,{get:e[n],enumerable:!0})};var y=window.location.origin+"/wails/runtime";function h(t,e){let n=new URL(y);return n.searchParams.append("method",t),n.searchParams.append("args",JSON.stringify(e)),new Promise((i,r)=>{fetch(n).then(o=>{if(o.ok)return o.headers.get("content-type")&&o.headers.get("content-type").indexOf("application/json")!==-1?o.json():o.text();r(Error(o.statusText))}).then(o=>i(o)).catch(o=>r(o))})}function l(t,e){return!e||e===-1?function(n,i){return i=i||{},h(t+"."+n,i)}:function(n,i){return i=i||{},i.windowID=e,h(t+"."+n,i)}}var D="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var w=(t=21)=>{let e="",n=t;for(;n--;)e+=D[Math.random()*64|0];return e};var I=l("dialog"),u=new Map;function Q(){let t;do t=w();while(u.has(t));return t}function S(t,e,n){let i=u.get(t);i&&(n?i.resolve(JSON.parse(e)):i.resolve(e),u.delete(t))}function g(t,e){let n=u.get(t);n&&(n.reject(e),u.delete(t))}function c(t,e){return new Promise((n,i)=>{let r=Q();e=e||{},e["dialog-id"]=r,u.set(r,{resolve:n,reject:i}),I(t,e).catch(o=>{i(o),u.delete(r)})})}function C(t){return c("Info",t)}function M(t){return c("Warning",t)}function O(t){return c("Error",t)}function b(t){return c("Question",t)}function v(t){return c("OpenFile",t)}function E(t){return c("SaveFile",t)}var f={};x(f,{SetText:()=>H,Text:()=>B});var T=l("clipboard");function H(t){return T("SetText",{text:t})}function B(){return T("Text")}var p={};x(p,{Hide:()=>L,Quit:()=>J,Show:()=>N});var m=l("application");function L(){return m("Hide")}function N(){return m("Show")}function J(){return m("Quit")}function k(t){let e=l("window",t);return{Center:()=>e("Center"),SetTitle:n=>e("SetTitle",{title:n}),Fullscreen:()=>e("Fullscreen"),UnFullscreen:()=>e("UnFullscreen"),SetSize:(n,i)=>e("SetSize",{width:n,height:i}),Size:()=>e("Size"),SetMaxSize:(n,i)=>e("SetMaxSize",{width:n,height:i}),SetMinSize:(n,i)=>e("SetMinSize",{width:n,height:i}),SetAlwaysOnTop:n=>e("SetAlwaysOnTop",{alwaysOnTop:n}),SetPosition:(n,i)=>e("SetPosition",{x:n,y:i}),Position:()=>e("Position"),Screen:()=>e("Screen"),Hide:()=>e("Hide"),Maximise:()=>e("Maximise"),Show:()=>e("Show"),ToggleMaximise:()=>e("ToggleMaximise"),UnMaximise:()=>e("UnMaximise"),Minimise:()=>e("Minimise"),UnMinimise:()=>e("UnMinimise"),SetBackgroundColour:(n,i,r,o)=>e("SetBackgroundColour",{r:n,g:i,b:r,a:o})}}var G=l("events"),d=class{constructor(e,n,i){this.eventName=e,this.maxCallbacks=i||-1,this.Callback=r=>(n(r),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}};var a=new Map;function s(t,e,n){let i=a.get(t)||[],r=new d(t,e,n);return i.push(r),a.set(t,i),()=>_(r)}function R(t,e){return s(t,e,-1)}function F(t,e){return s(t,e,1)}function _(t){let e=t.eventName,n=a.get(e).filter(i=>i!==t);n.length===0?a.delete(e):a.set(e,n)}function U(t){console.log("dispatching event: ",{event:t});let e=a.get(t.name);if(e){let n=[];e.forEach(i=>{i.Callback(t)&&n.push(i)}),n.length>0&&(e=e.filter(i=>!n.includes(i)),e.length===0?a.delete(t.name):a.set(t.name,e))}}function z(t,...e){[t,...e].forEach(i=>{a.delete(i)})}function A(){a.clear()}function P(t){G("Emit",t)}window.wails={...j(-1)};window._wails={dialogCallback:S,dialogErrorCallback:g,dispatchCustomEvent:U};function j(t){return{Clipboard:{...f},Application:{...p},Dialog:{Info:C,Warning:M,Error:O,Question:b,OpenFile:v,SaveFile:E},Events:{Emit:P,On:R,Once:F,OnMultiple:s,Off:z,OffAll:A},Window:k(t)}}console.log("Wails v3.0.0 Debug Mode Enabled");})();
(()=>{var y=Object.defineProperty;var f=(t,e)=>{for(var n in e)y(t,n,{get:e[n],enumerable:!0})};var L=window.location.origin+"/wails/runtime";function h(t,e){let n=new URL(L);return n.searchParams.append("method",t),e&&n.searchParams.append("args",JSON.stringify(e)),new Promise((i,r)=>{fetch(n).then(o=>{if(o.ok)return o.headers.get("content-type")&&o.headers.get("content-type").indexOf("application/json")!==-1?o.json():o.text();r(Error(o.statusText))}).then(o=>i(o)).catch(o=>r(o))})}function l(t,e){return!e||e===-1?function(n,i){return h(t+"."+n,i)}:function(n,i){return i=i||{},i.windowID=e,h(t+"."+n,i)}}var D="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var g=(t=21)=>{let e="",n=t;for(;n--;)e+=D[Math.random()*64|0];return e};var I=l("dialog"),u=new Map;function Q(){let t;do t=g();while(u.has(t));return t}function S(t,e,n){let i=u.get(t);i&&(n?i.resolve(JSON.parse(e)):i.resolve(e),u.delete(t))}function C(t,e){let n=u.get(t);n&&(n.reject(e),u.delete(t))}function c(t,e){return new Promise((n,i)=>{let r=Q();e=e||{},e["dialog-id"]=r,u.set(r,{resolve:n,reject:i}),I(t,e).catch(o=>{i(o),u.delete(r)})})}function M(t){return c("Info",t)}function O(t){return c("Warning",t)}function b(t){return c("Error",t)}function v(t){return c("Question",t)}function E(t){return c("OpenFile",t)}function R(t){return c("SaveFile",t)}var m={};f(m,{SetText:()=>H,Text:()=>B});var T=l("clipboard");function H(t){return T("SetText",{text:t})}function B(){return T("Text")}var d={};f(d,{Hide:()=>N,Quit:()=>G,Show:()=>J});var p=l("application");function N(){return p("Hide")}function J(){return p("Show")}function G(){return p("Quit")}var x={};f(x,{Log:()=>j});var _=l("log");function j(t){return _("Log",t)}function k(t){let e=l("window",t);return{Center:()=>e("Center"),SetTitle:n=>e("SetTitle",{title:n}),Fullscreen:()=>e("Fullscreen"),UnFullscreen:()=>e("UnFullscreen"),SetSize:(n,i)=>e("SetSize",{width:n,height:i}),Size:()=>e("Size"),SetMaxSize:(n,i)=>e("SetMaxSize",{width:n,height:i}),SetMinSize:(n,i)=>e("SetMinSize",{width:n,height:i}),SetAlwaysOnTop:n=>e("SetAlwaysOnTop",{alwaysOnTop:n}),SetPosition:(n,i)=>e("SetPosition",{x:n,y:i}),Position:()=>e("Position"),Screen:()=>e("Screen"),Hide:()=>e("Hide"),Maximise:()=>e("Maximise"),Show:()=>e("Show"),ToggleMaximise:()=>e("ToggleMaximise"),UnMaximise:()=>e("UnMaximise"),Minimise:()=>e("Minimise"),UnMinimise:()=>e("UnMinimise"),SetBackgroundColour:(n,i,r,o)=>e("SetBackgroundColour",{r:n,g:i,b:r,a:o})}}var q=l("events"),w=class{constructor(e,n,i){this.eventName=e,this.maxCallbacks=i||-1,this.Callback=r=>(n(r),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}};var a=new Map;function s(t,e,n){let i=a.get(t)||[],r=new w(t,e,n);return i.push(r),a.set(t,i),()=>K(r)}function F(t,e){return s(t,e,-1)}function U(t,e){return s(t,e,1)}function K(t){let e=t.eventName,n=a.get(e).filter(i=>i!==t);n.length===0?a.delete(e):a.set(e,n)}function z(t){console.log("dispatching event: ",{event:t});let e=a.get(t.name);if(e){let n=[];e.forEach(i=>{i.Callback(t)&&n.push(i)}),n.length>0&&(e=e.filter(i=>!n.includes(i)),e.length===0?a.delete(t.name):a.set(t.name,e))}}function A(t,...e){[t,...e].forEach(i=>{a.delete(i)})}function P(){a.clear()}function W(t){return q("Emit",t)}window.wails={...V(-1)};window._wails={dialogCallback:S,dialogErrorCallback:C,dispatchCustomEvent:z};function V(t){return{Clipboard:{...m},Application:{...d},Log:x,Dialog:{Info:M,Warning:O,Error:b,Question:v,OpenFile:E,SaveFile:R},Events:{Emit:W,On:F,Once:U,OnMultiple:s,Off:A,OffAll:P},Window:k(t)}}console.log("Wails v3.0.0 Debug Mode Enabled");})();

View File

@ -1 +1 @@
(()=>{var W=Object.defineProperty;var x=(t,e)=>{for(var n in e)W(t,n,{get:e[n],enumerable:!0})};var y=window.location.origin+"/wails/runtime";function h(t,e){let n=new URL(y);return n.searchParams.append("method",t),n.searchParams.append("args",JSON.stringify(e)),new Promise((i,r)=>{fetch(n).then(o=>{if(o.ok)return o.headers.get("content-type")&&o.headers.get("content-type").indexOf("application/json")!==-1?o.json():o.text();r(Error(o.statusText))}).then(o=>i(o)).catch(o=>r(o))})}function l(t,e){return!e||e===-1?function(n,i){return i=i||{},h(t+"."+n,i)}:function(n,i){return i=i||{},i.windowID=e,h(t+"."+n,i)}}var D="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var w=(t=21)=>{let e="",n=t;for(;n--;)e+=D[Math.random()*64|0];return e};var I=l("dialog"),u=new Map;function Q(){let t;do t=w();while(u.has(t));return t}function S(t,e,n){let i=u.get(t);i&&(n?i.resolve(JSON.parse(e)):i.resolve(e),u.delete(t))}function g(t,e){let n=u.get(t);n&&(n.reject(e),u.delete(t))}function c(t,e){return new Promise((n,i)=>{let r=Q();e=e||{},e["dialog-id"]=r,u.set(r,{resolve:n,reject:i}),I(t,e).catch(o=>{i(o),u.delete(r)})})}function C(t){return c("Info",t)}function M(t){return c("Warning",t)}function O(t){return c("Error",t)}function b(t){return c("Question",t)}function v(t){return c("OpenFile",t)}function E(t){return c("SaveFile",t)}var f={};x(f,{SetText:()=>H,Text:()=>B});var T=l("clipboard");function H(t){return T("SetText",{text:t})}function B(){return T("Text")}var p={};x(p,{Hide:()=>L,Quit:()=>J,Show:()=>N});var m=l("application");function L(){return m("Hide")}function N(){return m("Show")}function J(){return m("Quit")}function k(t){let e=l("window",t);return{Center:()=>e("Center"),SetTitle:n=>e("SetTitle",{title:n}),Fullscreen:()=>e("Fullscreen"),UnFullscreen:()=>e("UnFullscreen"),SetSize:(n,i)=>e("SetSize",{width:n,height:i}),Size:()=>e("Size"),SetMaxSize:(n,i)=>e("SetMaxSize",{width:n,height:i}),SetMinSize:(n,i)=>e("SetMinSize",{width:n,height:i}),SetAlwaysOnTop:n=>e("SetAlwaysOnTop",{alwaysOnTop:n}),SetPosition:(n,i)=>e("SetPosition",{x:n,y:i}),Position:()=>e("Position"),Screen:()=>e("Screen"),Hide:()=>e("Hide"),Maximise:()=>e("Maximise"),Show:()=>e("Show"),ToggleMaximise:()=>e("ToggleMaximise"),UnMaximise:()=>e("UnMaximise"),Minimise:()=>e("Minimise"),UnMinimise:()=>e("UnMinimise"),SetBackgroundColour:(n,i,r,o)=>e("SetBackgroundColour",{r:n,g:i,b:r,a:o})}}var G=l("events"),d=class{constructor(e,n,i){this.eventName=e,this.maxCallbacks=i||-1,this.Callback=r=>(n(r),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}};var a=new Map;function s(t,e,n){let i=a.get(t)||[],r=new d(t,e,n);return i.push(r),a.set(t,i),()=>_(r)}function R(t,e){return s(t,e,-1)}function F(t,e){return s(t,e,1)}function _(t){let e=t.eventName,n=a.get(e).filter(i=>i!==t);n.length===0?a.delete(e):a.set(e,n)}function U(t){console.log("dispatching event: ",{event:t});let e=a.get(t.name);if(e){let n=[];e.forEach(i=>{i.Callback(t)&&n.push(i)}),n.length>0&&(e=e.filter(i=>!n.includes(i)),e.length===0?a.delete(t.name):a.set(t.name,e))}}function z(t,...e){[t,...e].forEach(i=>{a.delete(i)})}function A(){a.clear()}function P(t){G("Emit",t)}window.wails={...j(-1)};window._wails={dialogCallback:S,dialogErrorCallback:g,dispatchCustomEvent:U};function j(t){return{Clipboard:{...f},Application:{...p},Dialog:{Info:C,Warning:M,Error:O,Question:b,OpenFile:v,SaveFile:E},Events:{Emit:P,On:R,Once:F,OnMultiple:s,Off:z,OffAll:A},Window:k(t)}}console.log("Wails v3.0.0 Debug Mode Enabled");})();
(()=>{var y=Object.defineProperty;var f=(t,e)=>{for(var n in e)y(t,n,{get:e[n],enumerable:!0})};var L=window.location.origin+"/wails/runtime";function h(t,e){let n=new URL(L);return n.searchParams.append("method",t),e&&n.searchParams.append("args",JSON.stringify(e)),new Promise((i,r)=>{fetch(n).then(o=>{if(o.ok)return o.headers.get("content-type")&&o.headers.get("content-type").indexOf("application/json")!==-1?o.json():o.text();r(Error(o.statusText))}).then(o=>i(o)).catch(o=>r(o))})}function l(t,e){return!e||e===-1?function(n,i){return h(t+"."+n,i)}:function(n,i){return i=i||{},i.windowID=e,h(t+"."+n,i)}}var D="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var g=(t=21)=>{let e="",n=t;for(;n--;)e+=D[Math.random()*64|0];return e};var I=l("dialog"),u=new Map;function Q(){let t;do t=g();while(u.has(t));return t}function S(t,e,n){let i=u.get(t);i&&(n?i.resolve(JSON.parse(e)):i.resolve(e),u.delete(t))}function C(t,e){let n=u.get(t);n&&(n.reject(e),u.delete(t))}function c(t,e){return new Promise((n,i)=>{let r=Q();e=e||{},e["dialog-id"]=r,u.set(r,{resolve:n,reject:i}),I(t,e).catch(o=>{i(o),u.delete(r)})})}function M(t){return c("Info",t)}function O(t){return c("Warning",t)}function b(t){return c("Error",t)}function v(t){return c("Question",t)}function E(t){return c("OpenFile",t)}function R(t){return c("SaveFile",t)}var m={};f(m,{SetText:()=>H,Text:()=>B});var T=l("clipboard");function H(t){return T("SetText",{text:t})}function B(){return T("Text")}var d={};f(d,{Hide:()=>N,Quit:()=>G,Show:()=>J});var p=l("application");function N(){return p("Hide")}function J(){return p("Show")}function G(){return p("Quit")}var x={};f(x,{Log:()=>j});var _=l("log");function j(t){return _("Log",t)}function k(t){let e=l("window",t);return{Center:()=>e("Center"),SetTitle:n=>e("SetTitle",{title:n}),Fullscreen:()=>e("Fullscreen"),UnFullscreen:()=>e("UnFullscreen"),SetSize:(n,i)=>e("SetSize",{width:n,height:i}),Size:()=>e("Size"),SetMaxSize:(n,i)=>e("SetMaxSize",{width:n,height:i}),SetMinSize:(n,i)=>e("SetMinSize",{width:n,height:i}),SetAlwaysOnTop:n=>e("SetAlwaysOnTop",{alwaysOnTop:n}),SetPosition:(n,i)=>e("SetPosition",{x:n,y:i}),Position:()=>e("Position"),Screen:()=>e("Screen"),Hide:()=>e("Hide"),Maximise:()=>e("Maximise"),Show:()=>e("Show"),ToggleMaximise:()=>e("ToggleMaximise"),UnMaximise:()=>e("UnMaximise"),Minimise:()=>e("Minimise"),UnMinimise:()=>e("UnMinimise"),SetBackgroundColour:(n,i,r,o)=>e("SetBackgroundColour",{r:n,g:i,b:r,a:o})}}var q=l("events"),w=class{constructor(e,n,i){this.eventName=e,this.maxCallbacks=i||-1,this.Callback=r=>(n(r),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}};var a=new Map;function s(t,e,n){let i=a.get(t)||[],r=new w(t,e,n);return i.push(r),a.set(t,i),()=>K(r)}function F(t,e){return s(t,e,-1)}function U(t,e){return s(t,e,1)}function K(t){let e=t.eventName,n=a.get(e).filter(i=>i!==t);n.length===0?a.delete(e):a.set(e,n)}function z(t){console.log("dispatching event: ",{event:t});let e=a.get(t.name);if(e){let n=[];e.forEach(i=>{i.Callback(t)&&n.push(i)}),n.length>0&&(e=e.filter(i=>!n.includes(i)),e.length===0?a.delete(t.name):a.set(t.name,e))}}function A(t,...e){[t,...e].forEach(i=>{a.delete(i)})}function P(){a.clear()}function W(t){return q("Emit",t)}window.wails={...V(-1)};window._wails={dialogCallback:S,dialogErrorCallback:C,dispatchCustomEvent:z};function V(t){return{Clipboard:{...m},Application:{...d},Log:x,Dialog:{Info:M,Warning:O,Error:b,Question:v,OpenFile:E,SaveFile:R},Events:{Emit:W,On:F,Once:U,OnMultiple:s,Off:A,OffAll:P},Window:k(t)}}console.log("Wails v3.0.0 Debug Mode Enabled");})();

View File

@ -3,9 +3,12 @@ package application
import "C"
import (
"log"
"os"
"runtime"
"sync"
"github.com/wailsapp/wails/v3/pkg/logger"
"github.com/wailsapp/wails/v3/pkg/events"
"github.com/wailsapp/wails/v3/pkg/options"
@ -29,7 +32,13 @@ func New(appOptions options.Application) *App {
options: appOptions,
applicationEventListeners: make(map[uint][]func()),
systemTrays: make(map[uint]*SystemTray),
log: logger.New(appOptions.Logger.CustomLoggers...),
}
if !appOptions.Logger.Silent {
result.log.AddOutput(&logger.Console{})
}
result.Events = NewCustomEventProcessor(result.dispatchEventToWindows)
globalApplication = result
return result
@ -77,13 +86,6 @@ type webViewAssetRequest struct {
var webviewRequests = make(chan *webViewAssetRequest)
type EventHandler interface {
On(eventName string, args any)
OnMultiple(eventName string, args any, count int)
Once(eventName string, args any)
Emit(eventName string, args any)
}
type App struct {
options options.Application
applicationEventListeners map[uint][]func()
@ -114,10 +116,9 @@ type App struct {
// The main application menu
ApplicationMenu *Menu
// About MessageDialog
clipboard *Clipboard
Events *EventProcessor
Events *EventProcessor
log *logger.Logger
}
func (a *App) getSystemTrayID() uint {
@ -146,6 +147,40 @@ func (a *App) NewWebviewWindow() *WebviewWindow {
return a.NewWebviewWindowWithOptions(nil)
}
func (a *App) info(message string, args ...any) {
a.Log(&logger.Message{
Level: "INFO",
Message: message,
Data: args,
Sender: "Wails",
})
}
func (a *App) fatal(message string, args ...any) {
msg := "************** FATAL **************\n"
msg += message
msg += "***********************************\n"
a.Log(&logger.Message{
Level: "FATAL",
Message: msg,
Data: args,
Sender: "Wails",
})
a.log.Flush()
os.Exit(1)
}
func (a *App) error(message string, args ...any) {
a.Log(&logger.Message{
Level: "ERROR",
Message: message,
Data: args,
Sender: "Wails",
})
}
func (a *App) NewWebviewWindowWithOptions(windowOptions *options.WebviewWindow) *WebviewWindow {
// Ensure we have sane defaults
if windowOptions == nil {
@ -177,7 +212,6 @@ func (a *App) NewWebviewWindowWithOptions(windowOptions *options.WebviewWindow)
}
func (a *App) NewSystemTray() *SystemTray {
id := a.getSystemTrayID()
newSystemTray := NewSystemTray(id)
a.systemTraysLock.Lock()
@ -191,6 +225,7 @@ func (a *App) NewSystemTray() *SystemTray {
}
func (a *App) Run() error {
a.info("Starting application")
a.impl = newPlatformApp(a)
a.running = true
@ -431,3 +466,7 @@ func (a *App) Show() {
a.impl.show()
}
}
func (a *App) Log(message *logger.Message) {
a.log.Log(message)
}

View File

@ -65,6 +65,8 @@ func (m *MessageProcessor) HandleRuntimeCall(rw http.ResponseWriter, r *http.Req
m.processEventsMethod(method, rw, r, targetWindow, params)
case "application":
m.processApplicationMethod(method, rw, r, targetWindow, params)
case "log":
m.processLogMethod(method, rw, r, targetWindow, params)
default:
m.httpError(rw, "Unknown runtime call: %s", object)
}

View File

@ -4,11 +4,11 @@ import (
"net/http"
)
func (m *MessageProcessor) processClipboardMethod(method string, rw http.ResponseWriter, r *http.Request, window *WebviewWindow, args QueryParams) {
func (m *MessageProcessor) processClipboardMethod(method string, rw http.ResponseWriter, _ *http.Request, _ *WebviewWindow, params QueryParams) {
switch method {
case "SetText":
title := args.String("text")
title := params.String("text")
if title == nil {
m.Error("SetText: text is required")
return

View File

@ -0,0 +1,26 @@
package application
import (
"fmt"
"net/http"
"github.com/wailsapp/wails/v3/pkg/logger"
)
func (m *MessageProcessor) processLogMethod(method string, rw http.ResponseWriter, _ *http.Request, window *WebviewWindow, params QueryParams) {
switch method {
case "Log":
var msg logger.Message
err := params.ToStruct(&msg)
if err != nil {
m.httpError(rw, "error parsing log message: %s", err.Error())
return
}
msg.Sender = fmt.Sprintf("%d", window.id)
globalApplication.Log(&msg)
m.ok(rw)
default:
m.httpError(rw, "Unknown log method: %s", method)
}
}

View File

@ -3,6 +3,9 @@ package application
import (
"fmt"
"sync"
"time"
"github.com/wailsapp/wails/v3/pkg/logger"
"github.com/wailsapp/wails/v2/pkg/assetserver"
"github.com/wailsapp/wails/v2/pkg/assetserver/webview"
@ -98,11 +101,10 @@ func NewWindow(options *options.WebviewWindow) *WebviewWindow {
}
opts := assetserveroptions.Options{Assets: options.Assets.FS, Handler: options.Assets.Handler, Middleware: options.Assets.Middleware}
// TODO Bindings, Logger, ServingFrom disk?
// TODO Bindings, ServingFrom disk?
srv, err := assetserver.NewAssetServer("", opts, false, nil, runtime.RuntimeAssetsBundle)
if err != nil {
// TODO handle errors
panic(err)
globalApplication.fatal(err.Error())
}
result := &WebviewWindow{
@ -365,7 +367,7 @@ func (w *WebviewWindow) SetBackgroundColour(colour *options.RGBA) *WebviewWindow
}
func (w *WebviewWindow) handleMessage(message string) {
fmt.Printf("[window %d] %s\n", w.id, message)
w.info(message)
// Check for special messages
if message == "test" {
w.SetTitle("Hello World")
@ -376,7 +378,7 @@ func (w *WebviewWindow) handleMessage(message string) {
func (w *WebviewWindow) handleWebViewRequest(request webview.Request) {
url, _ := request.URL()
fmt.Printf("[window %d] Request %s\n", w.id, url)
w.info("Request: %s", url)
w.assets.ServeWebViewRequest(request)
}
@ -621,3 +623,14 @@ func (w *WebviewWindow) dispatchCustomEvent(event *CustomEvent) {
msg := fmt.Sprintf("_wails.dispatchCustomEvent(%s);", event.ToJSON())
w.ExecJS(msg)
}
func (w *WebviewWindow) info(message string, args ...any) {
globalApplication.Log(&logger.Message{
Level: "INFO",
Message: message,
Data: args,
Sender: fmt.Sprintf("window %d", w.id),
Time: time.Now(),
})
}

35
v3/pkg/logger/log.go Normal file
View File

@ -0,0 +1,35 @@
package logger
import (
"fmt"
)
type Logger struct {
output []Output
}
func New(outputs ...Output) *Logger {
result := &Logger{}
if outputs != nil {
result.output = outputs
}
return result
}
func (l *Logger) AddOutput(output Output) {
l.output = append(l.output, output)
}
func (l *Logger) Log(message *Message) {
for _, o := range l.output {
go o.Log(message)
}
}
func (l *Logger) Flush() {
for _, o := range l.output {
if err := o.Flush(); err != nil {
fmt.Printf("Error flushing '%s' Logger: %s\n", o.Name(), err.Error())
}
}
}

View File

@ -0,0 +1,27 @@
package logger
import "fmt"
type Console struct{}
func (l *Console) Name() string {
return "Console"
}
func (l *Console) Log(message *Message) {
msg := fmt.Sprintf(message.Message+"\n", message.Data...)
level := ""
if message.Level != "" {
level = fmt.Sprintf("[%s] ", message.Level)
}
sender := ""
if message.Sender != "" {
sender = fmt.Sprintf("%s: ", message.Sender)
}
fmt.Printf("%s%s%s", level, sender, msg)
}
func (l *Console) Flush() error {
return nil
}

11
v3/pkg/logger/message.go Normal file
View File

@ -0,0 +1,11 @@
package logger
import "time"
type Message struct {
Level string `json:"log"`
Message string `json:"message"`
Data []any `json:"data,omitempty"`
Sender string `json:"-"`
Time time.Time `json:"-"`
}

7
v3/pkg/logger/output.go Normal file
View File

@ -0,0 +1,7 @@
package logger
type Output interface {
Name() string
Log(message *Message)
Flush() error
}

View File

@ -1,9 +1,15 @@
package options
import "github.com/wailsapp/wails/v3/pkg/logger"
type Application struct {
Name string
Description string
Icon []byte
Mac Mac
Bind []interface{}
Logger struct {
Silent bool
CustomLoggers []logger.Output
}
}