From 162720423faddeddcabe284c77a908196b357d33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 18:28:42 +1100 Subject: [PATCH 001/369] Bump golang.org/x/crypto in /v2/examples/customlayout (#3144) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.14.0 to 0.17.0. - [Commits](https://github.com/golang/crypto/compare/v0.14.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- v2/examples/customlayout/go.mod | 7 ++++--- v2/examples/customlayout/go.sum | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/v2/examples/customlayout/go.mod b/v2/examples/customlayout/go.mod index 8947007a7b0..005bb557d9b 100644 --- a/v2/examples/customlayout/go.mod +++ b/v2/examples/customlayout/go.mod @@ -9,6 +9,7 @@ require github.com/wailsapp/wails/v2 v2.1.0 require ( github.com/bep/debounce v1.2.1 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect github.com/labstack/echo/v4 v4.10.2 // indirect @@ -28,11 +29,11 @@ require ( github.com/valyala/fasttemplate v1.2.2 // indirect github.com/wailsapp/go-webview2 v1.0.10 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect - golang.org/x/crypto v0.14.0 // indirect + golang.org/x/crypto v0.17.0 // indirect golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect ) replace github.com/wailsapp/wails/v2 v2.1.0 => ../.. diff --git a/v2/examples/customlayout/go.sum b/v2/examples/customlayout/go.sum index 4cdbdac671c..4ec20616f62 100644 --- a/v2/examples/customlayout/go.sum +++ b/v2/examples/customlayout/go.sum @@ -5,6 +5,8 @@ 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/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= @@ -47,6 +49,7 @@ github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXn github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE= github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= @@ -54,13 +57,12 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/wailsapp/go-webview2 v1.0.7 h1:s95+7irJsAsTy1RsjJ6N0cYX7tZ4gP7Uzawds0L2urs= -github.com/wailsapp/go-webview2 v1.0.7/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo= +github.com/wailsapp/go-webview2 v1.0.10 h1:PP5Hug6pnQEAhfRzLCoOh2jJaPdrqeRgJKZhyYyDV/w= github.com/wailsapp/go-webview2 v1.0.10/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo= github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -76,14 +78,15 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 437ca0ffd5d42e1982e74b98143bc96091a94d35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 18:29:29 +1100 Subject: [PATCH 002/369] Bump golang.org/x/crypto from 0.14.0 to 0.17.0 in /v2 (#3142) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.14.0 to 0.17.0. - [Commits](https://github.com/golang/crypto/compare/v0.14.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Lea Anthony --- v2/go.mod | 8 ++++---- v2/go.sum | 15 ++++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/v2/go.mod b/v2/go.mod index a2d0ab416b8..0d04fd4114d 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -41,7 +41,7 @@ require ( github.com/wzshiming/ctc v1.2.3 golang.org/x/mod v0.12.0 golang.org/x/net v0.17.0 - golang.org/x/sys v0.13.0 + golang.org/x/sys v0.15.0 golang.org/x/tools v0.6.0 ) @@ -92,11 +92,11 @@ require ( github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/yuin/goldmark v1.4.13 // indirect github.com/yuin/goldmark-emoji v1.0.1 // indirect - golang.org/x/crypto v0.14.0 // indirect + golang.org/x/crypto v0.17.0 // indirect golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/image v0.12.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/v2/go.sum b/v2/go.sum index fdc18d024f6..f6d59f7ce96 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -250,8 +250,8 @@ golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -301,22 +301,23 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= From 3c7a2187db8eb101b8a3ec138d998d61ff7c418e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 18:30:43 +1100 Subject: [PATCH 003/369] Bump golang.org/x/crypto in /v2/internal/staticanalysis/test/standard (#3143) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.14.0 to 0.17.0. - [Commits](https://github.com/golang/crypto/compare/v0.14.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Lea Anthony --- v2/internal/staticanalysis/test/standard/go.mod | 6 +++--- v2/internal/staticanalysis/test/standard/go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/v2/internal/staticanalysis/test/standard/go.mod b/v2/internal/staticanalysis/test/standard/go.mod index 0c7e2cc752c..80e64f9cff3 100644 --- a/v2/internal/staticanalysis/test/standard/go.mod +++ b/v2/internal/staticanalysis/test/standard/go.mod @@ -25,11 +25,11 @@ require ( github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.1 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect - golang.org/x/crypto v0.14.0 // indirect + golang.org/x/crypto v0.17.0 // indirect golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect ) // replace github.com/wailsapp/wails/v2 v2.0.0 => C:\Users\leaan diff --git a/v2/internal/staticanalysis/test/standard/go.sum b/v2/internal/staticanalysis/test/standard/go.sum index d2c8dd68796..0517c288845 100644 --- a/v2/internal/staticanalysis/test/standard/go.sum +++ b/v2/internal/staticanalysis/test/standard/go.sum @@ -57,8 +57,8 @@ github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhw github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= github.com/wailsapp/wails/v2 v2.3.1 h1:ZJz+pyIBKyASkgO8JO31NuHO1gTTHmvwiHYHwei1CqM= github.com/wailsapp/wails/v2 v2.3.1/go.mod h1:zlNLI0E2c2qA6miiuAHtp0Bac8FaGH0tlhA19OssR/8= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM= golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -73,12 +73,12 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 33172946ca4ede6d5c83129576afad5c97f93f01 Mon Sep 17 00:00:00 2001 From: Lykin <137850705+tiny-craft@users.noreply.github.com> Date: Wed, 3 Jan 2024 16:35:59 +0800 Subject: [PATCH 004/369] doc: update screenshot of Tiny RDM to latest version (#3166) Co-authored-by: Lykin --- website/docs/community/showcase/tinyrdm.mdx | 3 ++- .../current/community/showcase/tinyrdm.mdx | 3 ++- .../community/showcase/tinyrdm.mdx | 3 ++- .../current/community/showcase/tinyrdm.mdx | 3 ++- .../community/showcase/tinyrdm.mdx | 3 ++- .../current/community/showcase/tinyrdm.mdx | 3 ++- .../community/showcase/tinyrdm.mdx | 3 ++- .../current/community/showcase/tinyrdm.mdx | 3 ++- .../community/showcase/tinyrdm.mdx | 3 ++- .../current/community/showcase/tinyrdm.mdx | 3 ++- .../community/showcase/tinyrdm.mdx | 3 ++- .../current/community/showcase/tinyrdm.mdx | 3 ++- .../current/community/showcase/tinyrdm.mdx | 3 ++- .../community/showcase/tinyrdm.mdx | 3 ++- website/static/img/showcase/tiny-rdm.webp | Bin 104598 -> 0 bytes website/static/img/showcase/tiny-rdm1.webp | Bin 0 -> 160124 bytes website/static/img/showcase/tiny-rdm2.webp | Bin 0 -> 143726 bytes .../community/showcase/tinyrdm.mdx | 3 ++- 18 files changed, 30 insertions(+), 15 deletions(-) delete mode 100644 website/static/img/showcase/tiny-rdm.webp create mode 100644 website/static/img/showcase/tiny-rdm1.webp create mode 100644 website/static/img/showcase/tiny-rdm2.webp diff --git a/website/docs/community/showcase/tinyrdm.mdx b/website/docs/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/docs/community/showcase/tinyrdm.mdx +++ b/website/docs/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/fr/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx +++ b/website/i18n/fr/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/ja/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx +++ b/website/i18n/ja/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/ko/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx +++ b/website/i18n/ko/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/pt/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx +++ b/website/i18n/pt/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/ru/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx +++ b/website/i18n/ru/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/vi/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx b/website/i18n/vi/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/vi/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx +++ b/website/i18n/vi/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` diff --git a/website/static/img/showcase/tiny-rdm.webp b/website/static/img/showcase/tiny-rdm.webp deleted file mode 100644 index 29339520ef782222efcd31895671e2c3d6ff035e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 104598 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ℑ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 Pd6)PN-|=RQWQ=pp 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 literal 0 HcmV?d00001 diff --git a/website/static/img/showcase/tiny-rdm2.webp b/website/static/img/showcase/tiny-rdm2.webp new file mode 100644 index 0000000000000000000000000000000000000000..eda1d826beaf8ed7579f9f6b9359c760f9b1157d GIT binary patch literal 143726 zcmeFZRa9Kr+64;1-QC?C65QP-Snvc1?iSqLH8=z(xVr{-cXxM(x+L96y8E2J&(nRn z_kl5LP`hNW`ee@e&9xLIL`4mmUID3!2+FI-v#UV^0RbVt{3SpFp@0JkNXv_xg8~5o zJ7&~GWxsyJKM6wQkU>NOZtn^J9Mc<#k|Dtf4FUp`ssj^&6r*Vr)%%NUWQuVMK%Vyb zS?~r+;kR2cORA0kTc_v5(oQ#O>%rwIzo4{|cIk+aBu})XuPsYIepq6X3cd{B(5%+kl8=YqV;B@RgEzYc-I=g5;{y`hbhKfShtn#H*)f8&_ zE!!vBB>}sN$#yYO+zX0ZYeZrLos9tJB1(G{etJ=TI6lotU;D?hKvvP$XPq=-_MQod zU4hO0bKM9!Vwwqo?;-de!BEV5>5tX};$q?XnQu!0PbVILhZR7($Da?LZ(4u;@Be@J z$J+dVbR7sDX8=ELy~hfJ?`xNn@sH@iU3dv5B#||<^#E1bH7o(dED(KtJU&`srSIV< zUIsYrjC!4Q2=d5is+?hRDDub%#ajy&grJ|-JC{RM@CIt6JtfbMt zkSac>r!n#@;-oapH|}Jwo4AL-hbRJab6n<{*&B=&~=+gSHcNaC$w(1%-c^P zvF|ay>V8(IvT?!s0!5w#C;io1{fNfs7V2Gg36*j)0wIY(6hV_b>`68d&`TX69H)H+ zbczp^3QU~{i3-kZ&KfU4N}QEN9KBcO2^VB!@hD2~YA??M&+D)aOlNs^_=(PEyQ)Rf z1l;2g5PG5$@%Z_v^;BoKS;IM@l^5)(;P7A{qcqVEIwr2etqf(%$!m@VmuQJA$aP{x6XN-01_Sm0KlH*Q@}Cb6M-+^lE=3D zp2x-=#Pig1>vL=M$@2&R@W2ZL7zAv-T-dmpcc1_1Ik_XD<` zFBU-nfZBjl1i+K|6U}qxQ|IHzwayU$yG7wX;KuS8u=Vma+%H$oPSTzqo*Ew$?oUoU zs?*WZR{&vWH+vr4fKdR&bKWdqlh2Tk$}$1;7zN=$T>>V}Y;Gqx%`~9CE#| z60^>C00;nx9jfjEmH^uxFApEYu0bA0?nj>F&RTceb^$ton8%fqmm;Mm*Y42_SbFwY zMYx-}wS4y2_LzNqrUm>%|g0KhJ$jLVeS+_#T+{KW*6XkWHoRk>!UM8ramoqN6Gm8TKw2m62H zDUdy8YQD8Vx_&Xiuj1JtHQbd$yK7z4knamymozPvJsRqk3jy}l&C1XFeF0599y%Pf zpMn6$YF9`AePJ_V*wuetwehLwX{!55^`R(izw|~GXG-U|6uWnJ*-Rz6j$k63|e=9Ti6nXw;+0sRM6~_!i89wY#nu-T1YV!WnDvF|Vv%iPi zD8VZR3`p#d$UG8pQ1%Tx(ARjvV6B5952?hr4vSKevs@W9d}5N;W60P?o0wYmCIVd| z^`1_Uby1}2?cl~!HK4+dU=pBMWp+0W@_N}Mk{!4X;Mm-a2B}(41JpFF^#&r2H?;XB z&s%Y5D~lCbjSul}RXuF_gBU{6N}Gs0?TL? z_WyMuf=`as6@IK$JzNy1T85BcP`3tn#H=dXQ0eM@B4VcdcHsWcYj|)87yzX%x+bZ? zkQEKsPh1p|sUYeBBosNPa8hyq^AlRj<75*3!#ckzZC~bD0P1OZnVi9}yz3dV%Lhmv zB|c2b-A4E1r=O8UC=hJiV88j}n^CPQFu!wIB(yr)O8a~4{-06FI|w*t%!$Jf&mHAS zNwwt@(d2eEN}kf$zNwg&L<{BPraYBO9~D8#yEJJj4`DpNKBV`DL!Whjm@A@a-9NoP zhOA{o07l;iUL{^^;|A48gz$X%WloVSbn#!&4T7}&2*DqhfY(gSSyU_@IGUXku(oKO zW$7L_*vTH7Z39iSw#SM_9OnDl9Cu_}#k#NtG3Q}Qo{T@lE4dC58t`Qd0)YUW7 zngKPU^s;fWAt)sAWA+!4>i7b;(^UQ`${3`M)VqiFqyDpoSLhwz1+90PHbe9We}?W5 z{aw9iVwMs!co+|ZnsB~>g9fYEhxTr+ux5RjK;pVs1 zpNbTka>i&|dU(SDb3?%%aF7^4lhyeak=%U@dD*mHsjx~N%cgHwQk7cp<*TF}#*Fy0 zVP|!{F0+GrCRAuA0baX$Mc^SEqx>VCv^Su*#6<>40TcIvBqE_|o! zkh_vf#jx)>tN}bs=2jS3yOzh48K9otzhrt~;E2)6k-;=fT2~?*I|Pm`y>NS>niS}^ zlu7Gmq?JI0!b#m#4797xPTV$Q-W?FLmuIu!$8Rn>Ls1DyH&TA`SgLF-Z(vsR9zQl% zvps=mvS$ZoD^BTVhHH1M=_``CkWQtDiFJ7=6()ixu?}f$z!o{NQF!L8+OVvZZn^`{ zBZDC_r@lhDaFG4C1I)CrK);+mrf=r6oRmw2U?fHoOxiJm0O&KCrt1a$_A3)s@>f3O z@CV4Ju%gQ(*>Y6Io@zkHMxl`Pw|I1DxWlp5va~)*h3;7)8M03T5jIY(8`_6zuG8P* zz5V@-bi!ZF_y#D;>+*V;yvM@3?wc$ZD2}xF00deUcFowws^t`_@f2qze@d38gF+rb znRD*L)mc&VzDUx@7GuR&xNANa(T-~NUAfdYNql$-NBAOir31lez<@*P#|P8)6Ys{z z1%+GRz}CB%bcK>6S87x!5Vtl`E%?>fWKqt;l*~w6BZa4S5RQR`eGYOwjydH&wXGTZUPhH?#<=Jq#nE1-tCzRdu|Ekk`56LQb>5?*^vwlu=HG8pXz@#FDLNc19!== z?3VY|NIk3vtCd7+@1^lQzyHAWm~VNcL%7cYWhTJXbA;^I3aBY@BelcnpBB2LTHZ7BWON;L@~HN zFVMT_=H}V3wiI0Y)ff+apOavxVfk%d_b?alT8$CC^Cm8L*ADxR3x2)je{_6h4zT>R)+vA zcg)!FmS)!BRm*y?jMbOYU#qKbk5)&MQDdCKO@`J4Wo`DvTvn=$=N(|vWNcsHKqfx$ zO*K>%>P(O8Qw_-bP>X9b7owRsc1dnBT`qwNU5m9alDGyDH~I{HtaH1*c1HBJF`18g zM~lCUd{u_72*~hb+79e?z|eko8K_jEX{0NOOMJs#xEj2Kx#)8{Fo4AM^-AbhB*WEx zeym2Q)H11l4xu*@4-045Nd%QKL-fyJ1A&`JxVKm$>F48Am+1u!;CYu%Rk!}inBds_ zw1F0{$uBbVN3KWnz4OHJP`f2Pxz+rDq~b9*ZD+?ha9b$sz3>1~~r!FIgM- z^Rl{XQG#(A>@R@u18_M2Qm^a8 z7?^U}Av?usJ8Hs?KBRM;?2|E+PBJB7Oq0Gorq++-k0qon;;2Bqo~c_W?@jxn?2nmZ z_Vog_ZqgP=rWOmc?ERbSW7v-d({b5^XS6^ZZRyr@h6aLknq4!iHH- zMqKt>)wO-wqW$k{$Z$E|fD)3JTdhg!{LH|oS-etVvUy~F4|C$^hb|_>g7B%Nu53{I zg#5mLwshbde^6gs$B~%~B%UqKjxGcVhO2VXiulE`Pmj6QTx)su?f8%x%WYUY{4CVT zn{Ue2bZ#)dMAXr=>UF~o=^y1$(C3I9JPHmV?@>3h3E4rn6|L&U3Jjw>q-<})84OPg z@`C+_78DB`i`>%nS%TG|A~vYm*ZjB^!T6Fd$o%kR?f=NYBF-;t^SSuw82x75@czc( zXg=TJxXN`r>&G*cxfz==+c#K4y^s-|f{WP<#;2&Mibb>v)FBxfwO+0#r*SeLdE^Syr4arL;z3-*6agtR!>l-J=V1bH2Hd>AvtS^Y7r~@`W z9D&U3cyhT%?5qq&6&hhPm@&7iBIYz(V1s_hqNDi`xP4scz$rJISpfObLyF4!!y3_8@x4ze0x+->mGYBc$L1Hov`7_gEV6~E9#qI7?qxU*60~H5 zL-4PTc%7HhzrZW4UD3Y*+il=w=d7G{>?M3C&n z{>T2u+ixi{2MK#wLtP%SNg+<4V=}pguOI)V=lqqj{=O`rY-cMER*a(m3TM1lp%dG+4jWBz%o=$ybTA&1p;K(`4w&ixeq*o`a5bd2gs2-Qt8XuY3= z|NZCwL3QBhh60g**++^eUTvpv=O)o`$Bx8Tlue{Yh>Dr3)o0N$R;xy?*CHhkz>`Kp zd@iG)mLG%evNu=MHf%u*k@3I$lNljC0)MKq=X_PhiNA|i)U1~}F4|$+KEm?&OePs3 zFg>QbSb@(Y1$580`?rq!-*U(^v>_@aFwq$2K;G-NZ-!_N*~H zWehvvhCfl<3t-}5n?Kx)=)$ zLYzJMOlW~lG2dI|S;i}~?uq-_;djyh8I^zGlj9%;O(x%CK^TXs(-l)J8T863I&B&s z8)A$ID5;)WW5PvHo&6G(;0Y!!i0tm_JZUIZu1QWWA!pZZylGJR7p>oC5d?vv!jtwjdO3+O4)Bj3@ohsmjo>h-hI=T{Edar!T}@QV^N75g&x za+!wNtXZacmyv=bkIk;gf|%of0_+8HzY03W_fClWqE>^^T0il(%Kxf?`Eg*uOlTPK zmBSTgH)_S(90npzyuZqcx`L4deY@S>TcKS&2JBpG zm8Hid?F)NGebR=eL_-X*2Qb>LQH{VH)G~Ns7RqV_d-fm=qbj?6MI=%`oq-+yf%E0d zb@MdcmG_ZsD1ksBk(Y(FQ{?Iz_cF&s_yf-qCs-AOw~7|UsqqGiC`D!fwCeYk;0$L(Pm)1ftXjCk26fT*e9=Bwm zQDLLhTUhiLpXGpQc7(E8M_S6mTtIzx90D6KDhyv#VZhq3y1LG^Huv=GV zo4i*YdSAP_k4EZ&J^M54N?s#X#!O6F>V9y_)q^>@{!x zWSoajQ(8*=`E*X30B7I3_v7f4UBN=jCe@66&4V8{EN-J9ryQ$2rjT{;HLk7;F1s;k zoqS-LKPF8*(>hH$l6{*M_)h14WNtg$=RXSp7x!uNl$PEDO@FYo7A>WmR1rc~733!} zjB|C+4?6_{8Y9>oC_HgZ2bl<=u}XxK(ttc;HEX@1q|)}L-J_A_Axf@2aI2w?q@JM5mmCnmOop3 zn<((p_v4Hni+DA*xtE~-^@B#HPjrLtm)x6=e`;=r2)f};RzCJ82&8q{jWkVrd}(Zt z%kGcyEm>gZgo1jmJqU(f?=_GM7q0BxNR8m7AY~bj?qqxH`Lb;c;T)iBL3nQWjg|K?imGjtn1G0?s!&^l$)PB6SD& z?l~XCnU{xJK}W;zwVxV?V2?Q5f*D6Vf3QG{`_15ilFmxaH_;d9ia)vM5+~;TeQW;A$4S>GvCH1`Hb}4eq zq}pMxYTJt210hgvWzp|G@vA@CrZO(^xM0KN0FTrst#c_1+Y&1jLqsySdX)?s6}(O? zww|j($Gp{B_O7Z-3{JED2u-?3NX~T~=R9JC1E1(4#UD+Q18r4L;9YW@X;CGCAfPer zTWKl!_QvBRfhz@2tl}AL&Grih2+e8RVDoLO#47d16~o;61e%O*i&25%15P9FVi@{nv($zu)_(%wC& z8Z!n(o%aZW{^p6V9CMH-5*#KD9k~rM?DTSd1l$( zTa0`33ZT9Iynogico`68MS&fPR+hOhl_^;AR?ZF^?cm|co^8U*MvHP!WsWIRHhrp6 z{|X94j%W)(@2KA|rET~^jBV#pj1IcOvcKjl5gY^~X~f3jxhpaQ;vBVY#guacYajYd z#fE;$ktSMUsI-at7fwq?Pagn1u%spWS@S4l#Mm54lQ1)L*Z2c9RjO!WK9boRZIG0M z7?tSE!@gHWvGk|uqMcpk-)P*2TJ=rVKNNg*PvmnE8x#~N!?A){eh)?J;QN@lEI&-V zRz9dyiKva*t5n)PFnMy-d5e(^-8|~zm}y}CB%veR_=43(V;mU5p6@8BI+f?3-rjEb zkd9GSj4i(o#Da-{Sf|5trtLS;@JUU(FnTQ6K}en=<8%e_-3SZOI*@raJO;npR&x~D zY74Z!Ws~p!Al$;s7IQTfz8Uwmn}hls2?<#A9pd;Ca;-VcQ*|THY4jo=XH>4^V6s@o zYmM%b1@ae792m3_iXcJlHE{kEB*{Hy>DJ+ z&a3TXY{{(h7Fam5b6AODoyr&b4Y57V&zA&QG_9QJFwhBdEfz63i-# zUI??nbn3hPHzd8z&}YX{q?x{FZk%I1+=oy=Z&`*oli+zmQLy6cN}X&UmvwiblhTCE z&clHW&ZM6DMediE7vBT*oFzxs)Bu45n#2O6=;f<=4~%Dd8@zn+7SmsesN#pSL*?^C zsWXD_kd6aSy5Z+~xFwu}_Y*6WA|oJd#3q0hG^nXY_LgAueUQPJiV+lFbPxc`&Gz-1 zxP&aYLgMNZk#TRsy$!I#UpT1_s(9Tp9E|x!X|~)eXWKl1vz1os`0sNx`=yFyHix-4 zFQ5gI$g8U-yupqXp+MFmlsXradPn!tgG(A7=VmkMnOlkD0Hg;==ucYq5D06LmoLdn zq)W+^h_mOsnMG-VDN10&xk$ZzM5cg3pWce1qYCJRhq&D+(|H;~hXwn`aH*NiI-#%> z)a`|TgY95;NT~DU9&6A!<7-t6ztDq}ID+i8-XS%YDp+lMbriC5qi?hy6+Y+MXC&Do zKH%|mE85*KEjdy&nGF-boUTwZB)6Qst7;-nP~eU74ioWeWVtMjMaFmkp93JGOam;D z)V)tUS?mHA>BOZS2*O_sRP^59D`)-$a&=#ZQ@ktjMUe}TI=cGTwg-dJiA!S4$J~M1 zN?*yOki5fmar`%Cwg>!Ujj@c^|!3B2ru2)U#-~_ zjw?Z@+uw7RP7I`7;wJQH`ARA(QJ2{U%eGj^O8DdleT3979t4^&m1%#^VkNch!_W3d zWBMzB{xMC1ZrJ<;PJ~dUv6Jx?3TXS%;mw5Sf>?S0+B9A~>=I;&$`*;PtMHK;R1w0D z`RMn1QriP6LZ-vDLD^g>Zxlr8D0D90UQQbkCgpz2vfhr>NSvUtYg5G}ebU3i!nFAk zf#eT!qaD?4v|8FIuFP+JR?O%r02%eA1wkON*m8@7?}$jEOy`k^0a8#`o=Cbc!3Q68 zVqKXNlMHbbztC4oVs~}(oAG=R15%yA1ENHM!`?$|(}PKW|Dj@#N}XZb`&o`l_%vJD zzbD5p1#-q=z-ekhe;I$N-I{Rjk74U~@ho+=Ho1ovPAcXN{)YrYJ%9mYU&8qn8#l8D z{3mAfG7=3Tv%N28EewPT)7at-+lK5lXD`Bmt7OJpLr>Y4-HR(zlKDYQupmcL1(rBy z3ceg#Ay|(!lufMjf9g=4X=ZDbm?X@!Sx2Vs9SA8p!(X~ReWhYsAn{{i)gV5C#KD{U9g_T!K;MVuZDCYZg23*kY(ZN3~(|Vc`8EYU``@|G14Ii;F{Po z@>))nzrS#<4H_i?c^e|Lk4@-}XDXs0txPJVJ4M3mU`;KYq(YQmga_m298kNXKpXwK zf?(3vWgc!!>t1GVvL}{AkAgSJH_qZp7@Saq9IKa_yQ@S;o~DQ|*1;b4QEZC+ut5d2 zK%$)()z1*!N9r5ai1ugOYSc%~jk(&x-6^m@krW+!7zW&LN?${0y(8(6D07CW9`eMV zrF^I#(pB2^g4qg{r;Q7aQ42y>OPvLx+A6+j*q4K;e!w)i&CL5m( zNm)))0ZZHGj0D@k67XMM35|%+IlyPgcYujL%kL_A^b8vcnS-}j=r=}*wqT1Ubf*55eVdh#Kqb%3 ze+m9SRf`nnKeFGEA#(q;w&sU7olSTSW;K*Q)dc&aVn35amC<=zmk& z{(Mi9-FGbCQ1mBNig}-rQ8`X+mPGLTH~0Ap*!bT86SYJm7>6_#z5?n(2=?*&B|PoX zR8_pC{>q=pIEK{x@8a%H2}gN`WRwZg#fw2`TZV|%_>NayDQybJ2xJv57=MfVof!D5 zQX6Y0bkA00oK|OKc658-mALjly#-v0%@CLGj9!rymLw0l&P016f6-WKDRjv z^SRlGk!J9zez9|;`JKv)cxAm+F!~I>{M{z;7hBIMzv)F=~nGcRkfhD0 zjCXi*#0udZ>`-_NB+bgto+o%hyb;Oc*Oo-$`D2Ft-vjA~@#P#FT_IL|IU#3guC8Ws z0_LfF-yE&+adeo>`s|B*V^N)+bebDiGb&c2&ysNxPQ%Coom8~nr?08HDNF{*>7|=9WWIA$t&cX<*qM<- zGEvWHi#QHk2>}_lK*oR&Q;#LVS^yB-{Ceg$_W>c_jrRn*WMLRwBnzx_=2I%Ukt&fOTcVz?Mdy}9q z1Nm&p5cSRzJZL4+LA(vB=d!y*CZD7oNF62zx63A?to_%{m}JLLxnhk&_-Hym)>x zndc6prRzH%R@lD%@HUL_U}j%Y@w4*k&6$;7315MYboGtU^Tr)B^K9<`Q6ST+%9BOJ z&v?X^eWY=#8JJp>sY1W8(LWtZf2NhcU#tPTW6tgn{9qs0@adwA`RhuHTm}I!Lq!+!5Qhj|Fz`bZxMoDxs z0>bldi>bo5(MI~kWgk?5J!s7S)0+2Bsh;5)(jfAMWLOcOWoT*2(QzgimcEyKCxQCn zQ3%5+3R@VWNU>ZK4`crzI_aMulLIGFZA0r{lQ^bT*~>&cbbYk{ucMeh+;7|pVWC;W zm(2|Kpid$PrL#67W1||a;5kf-X!fL9R`nz39LBp}fYEV0!8-ty8hJo?bnU=K*@WDO z&@?TJnYzz1=W}a94g3-bSkQ)K?!3v3;%V%Z7@1)kD#n;rHDapfN)eJx{RGC5LhZJL zGAgHgbRR#4-^hBU6$On52JYZBd>Dj^oewU;asOB+#KyVxRoi=^7uWO{=EMBulwfp) zSXQ7HK&v`sfs`OAT9^nDkEJ%eEj#u`p0yPcY=>PcCczs1pS<tLnN=^IF?NHy(S zy%M%&iGw0X?}8QizsxLuLW|$I47ELs?B&hEkY*4Uvch(vQxCLC-U9Q7s377bupq>B zUb5T;WDGYGCHe#{b+mcsq*}q#>3Yvl6-Ro7kbCdP<1^3f-rDEiu^+Y^n^Vy!A}{W0 zKQLIHsNdL7HY<5m^iK@<4`}r>4GsJf^QY<7JGf79=Q09#L$%%Q&DzVlnk}yap%+R& z>Nsh|7v#kzQ3t{r^UbV0lh0-adsT2-R(GEZk>$Yyy~k##Q^A&6Z1fM6acSLc^cs(u zUW7;J%$C-@0C7=Ll1XgbF`B`a<;Mdf(A=I{uGNV697+%5+69ISSL zNTDt~iS89F=YC3=$gXN|3G^nX5H_|bhuZ$I+5&C>>vC%^-zSP5wd>vZAOtsm3p1@K znvy8~gC2OnPKM+z*jJlYAO(((yJN%>u|RuYGw|(4Wh0nD7@dUw)$i~!fI1U>%^bot zeuZ8Nwvl7Y?J0u9oc2kV0Rc~fYR*G}2EM3lLfDj=DEFc|t(Qdze9ittNi93Mzh~(7 zWhIFW$y84=UAr(y<3O^RhY}7716l+(g(7F>j+TJS+sq?eZwGu<2Jw%ZbB%Ma_ZREl zW`wBsmaAQ>JOaYyj zkU4d>vr8*ULjH1ykl=9l;W^*Y*wMP%-CaTrq#@k;ov{g<1xJRM;gIKkOZMcc8!&D3-kP>7B6_&Am31rxQh*PzBix}hH-9u!-uNkbs{kCnrXPvprN}*9W zu*Z5i*cE^AEp*4E*cXka(QATJF*y~QT|K8^v3dolS$X}H>i~ z(dci5L<_Ng=!tvkZEpv~8%jL?R@-?ZtC`Mk8NIS>qNWF5go1+N5-E?dFkulIR%DY) z&^t@c{#hfT059upAR}pPZ@#EJTOW+lf8XvGfmS!w`(h>Zcs zL7b0Eo*W}wY6lrXm5W(JlDP6cy4_u0S$b_nxU}ue&;1mw_0EYn?DO7a=z4?Dl0N$g2K}DWUK(#naTZB`dra1SrKC>FZ z462pPr*;r-9_=C(s6OrWABMAonDuePdcvS^g+>_D8gZl~CjFaq1# z0p`Bwemb)?#p-|be$dOkWZVWNPif)fUWTH9?~p|Xq!R8ajZj1c=P9ZRHEo3^smJS1 z@`da)hqdGw(l6W1B|C@%MKes%oi=NCtXnMHQWVbbf+DiSG)3nh`e1HpAvQP=XtF6! ztcRNYpcEsA6RC&GgxPwDCsTdS53C^jl`gVOe~j3_TUM>rdnad{;z>3-M@CFoEABQQ zkd1r$>v*n5qEY%f!NoYfal{KNE-AD{Y=bv7Yer$)vVy(B>Fx6}nQ%+J{OW$@3F83N zGGtmo5G5K+b+FBhm>2z^8#)X8zNfLJi-WB`fnoLF1M!0@xfu$J6u>5rD;fN=YTa2aL6;JP3Gf2 z3y78LCu^JS$ib_{!bX973}47a%T_TR^8$ka)t=mSd%6Rr!anjXLwQ1(E1I-740{(? z^~K6omsEQPZpTZ~Ew(LuN>*3$aVW|c47~mR%tn;T~ZRT3eG{k7yHHMBdIy zByPuTX}E2c1t_?YT-mp+xqYVlqFvnb>h9-gLx~4YM90zg1RlM#H0vw zNXZ{zwC9bD1V-sh2m82ADMD!050HDDC5^n}UXD(fCfhYs`0HMrAeC1Qdbdf5+{21- zS;BP~`r8u$+O`eoDR0;(9GX;n2h);jZ%0V$5zXXpfV-wuzxSZI;(v^ger^T((GdQO z<$XGB7(twdo%2`}4u~f21Im>%?WD`lqAtZxxDfTn9LIa!CcJmQyQwy0B#(E=!spEx z-}ON2q7SU32pVQ`-eih$K~X@3Gl4VOyOH--?)GgO|KiB_V^f+p4h#PP!EQC|P#unu zzA0X1nWEO;l(Y&HwY9hSk8~y%`4S#d+JKp4-&OeyLe6)!cE<7?#$<4ky5OtGo@quUJi_3F z0b&BNWv06(da{0td;We5WX7*TpNpfdS@|ZHhNj)UfgdG8$Xh6DNjT;&@hgL|kX*zR z8WS>hOFKq+GYF{lISi^_v*ETKh=G6gIYAn1j)hw@X{zxkh~h1)=%KFKQE3|5q^P7X z1ear66d$yDhT4$8M10_r^c{Dv*1^7c$+3Mh7vhG3FL-0I%1qb^Bn*a&?5hEfsK z6{1#7U5`V-rrH8{k6!}dKdi6vXawQQ-X&q1Wyn|{Eya-=mC3cz&jF|#?;)r}3d%C} zVG9&`yA>*vw(7_<{SqEU8t|EO2$c7O2Ttq)SU1Wt_Na9V16QKv+wM!|+L10ob>_jX zY6ig=pakMY&5svWeR)nVRUUSP`dY_|Hd{Mr(y5y@s6rdnY?U@oYa=q~Qb4WgG{y6d znL5uG)<-%sJLnXni#XJpJLxFn1`gD)k*_~DUh%yo%P51SH! z=8wi)yQdD&5P2x$^hZdIr3;b0k4W!; zVEjuZf#er4nieaoPASV*eT(Y-Sxir?&a>e$PIIU_03+eb4P*7JGLivx1}mQ{gb zd>l3`^NT25IBl-PRke1K^1F)*zO6MrRHWmx50DfI?Ft%_?sUxYd#^0kyr>?;-nYw_ zU05hK!$|=DZtn&W$cno7Q0aDY{`*k-5x`h42PS;aU^vHc6bN{jEmVJHvELw!o=gpT zFQ8*Ms*d<0dVw9N>8cpmmt@@%HbSSClv3xIikgF|&3F4#gnQhjBI zk<>1>)t8eOmib!&`RSYeUT>@hqINNTdB@^12V6HaV_=|cwKR$Ekc5a_rD>9YWU&9@ zzSJKU);8qgJ@?z}XC}*iRQ%Qmp_1|yh@{ut0GN6JDH2r?s`blz1)7@CjrITY3i*eQo z3S^3)%+3grXiYcw`Zc^|e7(?5H6tv6;M`F-;4FK8%{f;AAyKy29yYk}^>Ug<6T-3$ z0W-|8W^JE4Y>*_xi_VbkJ7IEsuvM33-Tn6GKdK7mZ~xR&Bty4yt! zg!o29H~wE9h3_i6c(Og&7rh&pn(qAM(fAT8V}%DZzYmEc^js)0ax1^Jg>Q7kq8iQZ z*(UESXD8}J1g5QOlMQh@jlWI1EF6-!_Y}3|1S2A9PV%!s$<^A@(SJO^=jU6-SSvHdSQ?9d_&NSjG^O|Dl9tyNMx2C=qw^-$;N-P!-{Lnh6Z#C75 zlT#~#hP*I*bBWlU4Ja~UEuQ;fD?l~Ow$u!_k0 ziuuK58G&kUWN)f*2lD#I&4pMlg{b8n#Ww#-RSC1xSui6!%B2Lo;IX*u(eR7T{IZ5aW}Vqq zOKAHFgEmlXa2B0uPkRsX_dKzlZIc{E0uz&{*QQT=5TKo(WJOwWK`Jso@6M{b^n=Vk zFL0A5yD%;GVb@7D>(pwh-$2lJ!`o>uzleLz196+t?m{ZWBdDE2}~j zs~mX>9}~eHn5XWx14H(eR9vg%3>+Xuvh zSVXWWmHUBBJIRuif&H_Gj{p9}iHtxhX6v>XO_VtyXg#EVo31%w3CN)(9;F1bzr65S z`cVLxew%vj7S~0Sm!0~zUE9pMTMBpUytB7hRv1K*gIC>Qd`X7c683u*Df?!)-ZdT# zQGFFE*}_i!_p~WldO5V#2nTk!wOjV?$uQJ`&hJ7T(<4IWIF)@4wLr+|YEeom6=fS= zt3^X}6SSazSg2>=ruDD^==!Tem|KMN4IJGgHZ!W8*0nv1vyK-(&&|g}*ycoODj_%s z#sx0p8JVKc@NK~0iUivPjwGtdXYj;!yI5hjElrp8k5rwcL)i(kA{Bj>*D}%DI5HAn z>ZS_$y~XqO)XlB+isuwZflh!4H2O3ND&1GF*p0q?RoN%dR$vdV^VrRexUyy(KQPGD zdr0s_8$V_Mtw>!rDocmAuj~@;s6K2dOceL@mgJqDUA0dE5b%gXmOIyT8uE;Wp2MLU0x4Kut;D83P+cm0@OQa9Y}$7BZ2M>HR9(~WFWF*oi32+CBrYa$4kn4c|$QG zP0XUnqV+8NQSbbyC^i{&W7>?SO-sIP9`$D9rfzK%+IRV`F7KWmgof3wB^V|5`z?W1 zpBJ{e!I=eXx7zJ&;SI#_eHgE_R(b5c2r7>Kr$m3KC2-Ou#B-m33njpW0T{KD41K-o zO0U|rPkSAZKD7~X0QSuj4RYlT-Ds@`YNhYyw_ENLD%@H0o-X_Mg{&cOP2WLxLOsGz-toe0XMV>as{Ua8iuEq zF3_5|p=4USS*Pc3{ZC_hw$y?zw2oK)d( zvoM3!B6@!|^j~8h;t`;rdOHvI{$R2zI38Cp?))?^+WHz52|J^e37tNf2k#DIXF0X#n61U9Z{&)dyD z2tVBF86GF6;SU)d2yj>pQ`J|ncv60eUx|RZ7b)LYq8v1`dO5fa2wB(^HjCNMLcOBq zlgVl%XB>X#P+I130<2HCuM;~j!CB zzlc8TLO8A>IVoP^Uw?LRhyp>d^&d}rL6rV5%K@1tZs3>@w8eE*dLOWSQ`Yqbw3@2; z0ZdG^Vrs~Ef0#Zt3s~5!;j(r>00U80M~VAlEX0W$@)P!KaqbY@&eXxWdtyKR)re2h z-O7HiL>cP-8{Hj{r(=Q?Tg1~A;O(c_>j|-2PkV5KH{ahw~z0AM|df zrX|p(GGh-lUV4)_VlbBd^~??CEi2eGKAk~B&@UzWWRH7I_^Ii{%xo5%sJc<)Y8Y~~ zY`n$)_xwhyGN$8VhoFk(B$icWCKU?ak`-La#feHH$8MsGOe!6YK!idvm*u|Tw0<9d zVvhoJGfCV_@U)Y5%AXoSsBk@jAkTp~B0L|0xxT0<9QdQ3h)Ww{X^%8`7mIKK1pRdB z9sX<#FyYuhJ`Z_5zN2e~{?KEvN2Pyr&<5J+yY%WO+T2XTU!@U0fhFM0h4liExs21L zNvT{Cqb{IQIhzMYI{EK?_5dwIFZq7q#!v!F^B(jo?m<$5A5kgf8>a8EH9l1=eerBdfXIFO z!Op*t#oJc_0fK!wNl6Zp)aJvVn%ZDw!KZCu4;3vtGQwv5{C*VJX%mOs^n%k#;(iT& zARc0!kB~fbO#Ft)W#7N(EsffnR{oj9aZllmBW@?No6q~)en+pH$%g3zL}93rretmZ zM!(oXpKm*FxM24@R3Y-#fp(KjTFxVVAYM*C@%^<0@}=kP`{L**5L+^_5XRSK>9Yew z6uzw4J9MK?l~u;r!^CB{8Z3L+3X%?AZ#BYiuA>hfjGZ_r15*C94e;>{=Zr zqcPlQ%z1=fPbHsw%e0xXsFX>uEAMk-+2b)QP<_{-Evhc%)@Z29zWP2?Q zqX8q;3USllxq@PLH=GL{s9DJ{@e8U8BcYfvTys4ZwC-Y$gat}sm~S?_%*Q^x7L1oUH&a_ccQH^0upzi~eV- zxRLRzI&7TQHkGeh3g?cz<*&vNR*t7MM>~S~)K6{t^9#cp!qLJEj8m!fgUdcPj{z`% zj{pU_DPSPbs)#_Su_}MW@e3{kX@j(6d21~>dG3yrl!hK~C2rUj-3wP`@V*pM_ccP$ zy{c8Xl8LK9e#yRV-QQ`#QU&GPYq2&~{|L)ox9R!OkNGoyKoP>FKcYiF;T-qZE2?)N z8_xwF_EYH6-vyqocrC(04pXFc1wIaBMW|5oIj;ye-y{FR#5whf=`BaJDuc9Kg<8acW?>bc^m^mMmrWO z;Y&yWGRze&&maH*Sf?2y+lK!=e(z0{$VhwTrCm=H7%XLnMF?dh^Mbi8A-I3;+}X#^ z?CaIuxt8ApU}aj1aEE7gRyEU|mh>!i_)z0$@|HJB$Wt<8if50JrKEM*Tf&XR;|!4)&sFfX<$`#gAlFF;tO&TuFYfo*a&60pB2jtS><^*LKpOZr!D)9&X1Mu&nLL_fk2jTC? zct(7(tLxJO9=_r*jPM&ioA?xH#Y4A>?Mdma4h+HU!M;5%`MCSqF=%hTPdR}ZuijOJ zO*ZvGP7cgF6GY`wNJQW1x7$*{p+E3_e8ZEsIfuxP3KP*$HMQ zo`Y!jMBiGgz3jUuyNT-bQh~6UXe{KyNxbzpElrFC{@p4B(YAQg6W-xs(=MGjEV>hD z+o>dKZ8?`7g;flYg%-5J`NDEtX@($?xB^$#ATVG9w>>=TcF-7$#gxT*%ewso6IkuS zLXv>IKcOAVYef)grN~!Uk7&3r^r1`v2e!@{zWnEpd9H!qVE<0e3!_S?cs8|T;>GsF z)5YR8>(<9mkhsx%oUl|4+~)D>Gwi}i?AbPUTCCL|0rw4XIOf;?~ zpyG1KjzqBGS`H~z+FMGOUPdy$Pw8D-=mMnx-3Gby5(rPR>6YpHd^%$T#{>07>J!(t zzyVq;9A;G+8zL#S;Cl{X*nUHSE({BXb0Bm4PxWD^MZ-VGHfMyFNsbbyL968YYWX)E zu8({wY+Bvxy9YsQQ=-q|munDk+zR$yEqn2ixwh*Bh3I|MQt=bWwQNE5(!J11=`N+J zDi?wojiL?$6}Q4VC?R!Fe`z)h$NQ#;90b{YtUhgFo8d^pbGgl?uQ)}W*#YqDgP|bi z$(`;0@oz(SQy4&MlML<*hGpLbNo_CFt7sU3Ezjt|KC(=ruFBWN0#&@-XhV;*u^`%W z<&aVi9PI)W9Nn9W@P9*P-$x5nvUgCA`ZOjUYEv#p<_@TR{_|rIxorw}cLki~xSEdy z6~R~at;h?8C5D@sQSt3`+?|VsrLsgQ0&J8OiLFnGYp#$@U-nA;BukITnWIZ_Ep`;2 zQOyg9;4VjZ8Mx^T(wu@wOq6+i@K7~MGRWZrnOj`{#uluve^xO|dh6va^{%|J0*8_B z19ZzfL&Vc5BK>Ucq$QAPB-x7kzyUU9`xY@s9P7b8QsEpK9RElT`p zb><3}&bLtA&g=Jw>F02J>sQ`IGkZPI24rT6xvGey*S%L`QNo{V_*>XmEpnsLBD)L~ zVEY2f*d+kkt(nNZ!4WqV?WphP+ddt-Ger(*)+4M2WV#9Ggip=3R7f#1i)Gm%h(V_m}6wb*dH6BR-4^ zk3&fOl^-7LeG65o-o32_BlXXZlAHvzKPjPdWg+g+$x0jFhhC+bcu&rUaU>n^mB7Ouz{_k#Nm>Dc=`(!m@lobFFl7m51c#E+aRWK1FNUq)4?2W81z073Q+zGX+WmFk zpDj`v7ep~7m*67X*2~QA1b40)fVTz7fYG@5lr%yAf2Gq!n(ccvl3f1I2Oiy!9bttR z&SRev?Oep^s@!&@RN%vfR|TtbK)zQn8Mv0?e;PAHlxyVT3Uh7+s?=tndf54X??k7) zX~y_Mv)XK?{KMqM{8oPDDEIfjS{yIusdw@(hy!z#V$n1-Jy4_+w?g{rT@bEpeB+?tQ!G^xn~J)6e}wYyIT}y9j-U zPg<8N5V}m(-^|t=;q~~|s~Cw#9zx!3LZeXRz=X_L5FBp~GUOWfWVc>t_2TOS(}C^m zMetG->}rQkM*XItOgXO0ZUEA%?o5bYaeKYsM+Mv#YV*y(kg9Q}7morE6X7`dMF?$LyHnTm@rgo*k-U~u* z;&DkNlAAnZ1GZ0#X-u6jUmO4c00001l#90_mJoUpD{s9%>-@aq+%~?6pW|6374@~j z$Bz%KZPd~PytP##A}|Qdxs%LJ!8R9%DZ=i**?j&UrDUI~gstt(G8K&hHo!aR<6JFGG1cZH@=N5L8Sr80zM5m$K7+2TSrDkkt?mM*uj!*z*S53$#&bxEhGA=;yV% zWKCqL6cjKJ>sn552l!N$T!SgO77@&(B(s~U)?TRMt!&8AYeqOQIa^GO z50Q?e`RDJ?yaxmqBWe>5Qh8R;azFq825YZAzA24&P^?ehIjG&J*1SoHNQsfkS9m!sSDwT@mcN*dg@?Mb5_APIMFvG>+m^QHmcrV^4Ma z1SgW10VyL^HL{|}h>3^GtoG0Y29@{vX5HNd@z(7wvVCyI=jW=UyifTuW>P7?>3a!E zI}G(`DuvoBY9wI;h|~wXGVtKZO^YP857UG2-Vzn@13!x`T!QccNGOz%?B=&8>gLyJ zr7-qb;(G^+HRPHt+rY!Z)28jFF7aQQz)!o2QP(fG%5m2tLa0^eK8TA_S;W5ZAp~ep z_3-Td+u)gzd+iF>3nT8oV&M%=K97>jVhVxd;Jq^p#f?HP*8Ag{nxMP+BDRKK4o$G{ z8;!DoU&|TM1xw*ml6eYX3b6ZIiOtr@2NXV zi^=cd$I;bIH|{1}_Fn|jk?kHnf6}pr0Vk^7xNRc=lBk%TYJ29Q8Jua|ZG&-6Co=9q zd07*8{iju(!cMfDjcc19jpSEVxGv!*_XSZ-#aMJ*3}$;9vB$vtzkm9uq(i&c1R+N1 ztWU>d{+H-6X?s={+o*1&*07&Q|9kfCRHSg?rUEdi~$~_@lYfOyd889*BuPb|LmLG@p~a*mcoh z)51v+k`8=l;d)(hZFc7{kkB%7j^++fEY5iXlPr3vxIL7npg@7Q$R^7S>7UVsixh4@ zcXQI}bCUJ`{Wu*oz!(8(X&%zX)Y6ZDiC8qX!Lvn6S{c<@DC1!QE(tnRpcOB*Avh>a zZf1eWBBbhqqc$C!&J3zCSeDJLvmE(M3di$9X;@Wcu&(pt5MGR21b625`o&H^ zc}kQ*o)Yjix#I)sYwaaw9{!I7sa>6L1gJ?quW0G@k5d_Kh44BCan-s50f(IcY3b?2`&D(a##DNQYDj`%`RPTe>mJABB#wXeSDmYFK zdn&uR7p}AZSeVVaXv;;XPyZbxOLsK#`nU3!2lGIk6Q4~3c81TXmI(5jtp$U*>qO>`m}p*F6o^k zh`zs!UkBe+k!hkw*}nNzZxrLL>s@d{gVZSbcGxgACW?Y%m{hB;zl~l<^qxW7rc0yJ zD2W8Gj{7Y%eVC!kO9`PjGI-ow`ukK8)=)wS$lDR`F*rfx4&dg>T)Lm+ReK@aHftw8 zkN%RiV90|g+{X8zaNtm}a0!)Gav9pD#N@S0vQ>Y~)6;4DG=xK`1Y+JyhZn|KEjRl2 zjxCW{h-KE~RCa(Kl?SXz#0&N7G1W!ozq1v_nI$elPC1iqwP+;GyP%*CjM#|D_IrSK zbooSn{KS?Wg0A`NX33j_NIV6;)6&bDYo!SwPD@nGC@_OU`w16~Nf0HN*&FBEMd{P`0s4vmGZpSOe_R&b0KN*@L&JQR3<&lDaG z*A-GLYWWBEStbWaoLlCFOc1Vd7xK6O#ENKw7`+}BKzIBHWcj^#7F|n(68~~~ydrUaaO!P9-cmml^%lvsjIjbb)TZk(D5djX@>yW`O~{>6 zeS*zOdN>y}2F0uR6P%+3hhNJP{}u%K(YWnzAU!@I1M<3Qos>oJy0Oi1iX0=|-lbB> z$ANt#%|myJzcBT>{Sic*1xl5GIfW0t(3TDqKa@HH{za_(%Atk?sBcZ+kA=r74BxtMU5`)bfI z*>$u?l#qeqzmnlJ%X)e;_pnZ3mV(U>cs)ARN{^QOJGOr(J6#)uMkU41S^p*gf8YzdK`C36dkpfu^gHno?!w3X=HHM*oG&K~6W zxMd2sJq&;6-S5Znlw|&OPrSlk*!}B#QH*BW>2I31q%fJvssjVtCL11qK3BDW@!R}k zY03M_7`R14Amw6f>&ZrK4+D=tDD zxlXs$7MO{M3$pv9nkcOYub^LE7i_0S^N%jBr*QCmIWj#U1h}EIzl}?~n+mdhm%CaF zHGwPW1?J3`)&Z+9$$BhN;NYs_K4Q>`81D{4Kr>H=5XPtG0HldiH4(t{NTLbdPIZ^w zDK%scT0rSg-}iSX($IxVN{$D;{+-MBjAb8LrjX}u2^sv5 z|LW0qQMi5NH$;?5aco`aJRyulf5Pl>8M>=)-o(4M$-t><2KAfD=kLyp(XNf0dK`LJ z5%w;Z(-~sA8N4JgTug|ntw+At{3VO@rrarondp!NefQA|8j69|qNNgI*4vHtr!1Zk zjiINY^_Fjfu{&KQTKDE;2eKx)=aP~K)$DYY9LU_ZZ+e$u3d8Tq$2lXsj1;4q)k+2Y zyJoVp$Km`DEo$R)PbgKz?-{{*K1}*<6ef6oq6|t^yEM;>P%L!zI>}GO8A$!iH&U*a zjDu~Mb2X$ty}1-`N{2sMpVa>Akeo>`$<&Hv*xLbZ)88LqK&d^W! zmpv!jv!Vt#;8aBhPFmEO&Nu{RY!x{p=T0-Din6!Cyi9MXNGxoGN+Rc~o;sK11Jq)H zY8D!1%Vm(yX_s(RM)Z3A3xmHva$@YoM=jgoF3?)47mc-Y0k)rRI7fh%K*<4(wVIB; zNU{r)c-@Ho!jmsAvX{NM%$HafZ7^L(z%dHLxYaN5EH_o#FWU3zcPW3T+fBM%&t!Nl zEH7>I^JHd`u{&k^*G**b*vspjR%z=rI^{WR1PSYgYSKQZpP~NDL0D~YuZgEZLa0NH z6f-VG(vUKri!KSw2OrX|86N&l+8uIt6~YclI#AcNhp z#015+HemPX-#(hkI^=-uCvhwMA!s^Q+3Ff0fTZ_k61fB+u(kKUAy;>&Z?V1=@~-Jp1?w*=m7v`Ytot~GWD0ThVM(eXH!H+hJKdh$52)e2M2ec|F zuucmNxxCHc9@!=p%q<3Ykffype*!pjX9*WD&+g9+TRv}*?r`@zJ{U9f^ed5dDu5QY zc=1`^r&9aoNOCxr!lrbQ-M1~iCg)jqE{ON-Lhz!M|4)v@ZLrvh%DbOAWfT8LRT^pw zzrSE3*Cv+K-?AqdiC!^(hr%cU18#4D((84l0l^M*AZqRqt=73Vw|pX1JmVFoAk!DC z+{aTiy<_42xZ{yK|Aw0HeiP;jR9}gJZ2t~QO9GJ**I7rQO)6eRW~cgkLBECQuG#o& z*@PTC-W-MyF@;e{NKeEMK6hx9$9K6{Dd#H?P_LMF-d_5?O9p~tpRmec~+$Xtw$fEl5(Uh3JfN>)4F5g7hH zEY}sD$O-vR{OT3Q(g;%jU17Yzd|jp5jK*IKUFs*{qSV^$N2#<9xYG&3qhr!uaMACX?|t)g~saT z$eRO)yT`CYm&x;)iX1zK#cX#LxfJqQ-6=Y{^B`lPvGC>B1joBa`Yo<-?IgB_c`rGa z;C>)1R5u)2;uTVR@UyTt(tZp3hi+;*wEFm)yiJ5HwoV|vWrC%T+emov^nx_E(id`# z%Obx>^+`8qCz?{Pj;qg`X+ujSl$7{=91=*=$jqgbO&m+@h8R1N_)ug#{)qZ!DwUQ@ zguASda5ooSnf>+T(aQ#i^KFbYi!4SK1T+Cb7Vhh@lp>`uwodDJkjXSeV5SDte#+P zIXbvjeTM7%$k1oXPLm%46-g{kZi11+aycz>aneqNuG&F@PE@*KU4vFRtvfMDNq*n= zD#}7*JVCowL{n4{w(qmY@;*bcg-=6IG5Vukb&M3dwqwre(o8i(rrMjdn#l3_!Y;Wy z?m>8h3HQn04z|v=Ur~x4^N=C{z8D_t;VK_*gn1yq+|R%F-y^AVcrRA|e!y~1gw@Vs ztXsZ>)W+&^?{STI)Ua3y?p=9M9fqD(KSlf+14>-96N4evXHDGqX|t@QFG9TAV zFiHWLOn0IKFg9-CWJ7iM?v4aiJR+@J8gmr6*K%cUh^8~1Kk{+($Z}5HcE4C!*$4d9 zN+k0?kdnrVF(n~L8}e8!P13|Ek1MICV>t=EcnI>$lif`!esN(+D`!zi2$TvpU{%#R zFEU=~%*MgIvY22f#R=>03=hMSWXp!pSKW83pnC5b9SpU41A2UL)!yR=$HLybvIy>* zUWS&t_l+SmU|G|wi|a>bfCSYgerEeyZPxa8(9f{JLwAKsf6UqL>E@lktdXL7$3xOu z%Xu+n>xiz@;P-w9NcU>-WoO1U4aWwU)_MX?9l|yMlg~vjU9cf$uhO6lSxu)gZ7}ZQ zy&Gp%8R?c2GlT#jlaA`cbL#38Gk@iVk4#rP)Yji<*8Y9k*z5S)?+bJOt&-YI zOpV1joJL&WzT{91XSW_MVCrz7tXo@ zcCe}+%+4i0c?pS3hCBm^6X!fbd?T$KxA?Cb=}@e_cJDxhA^>AG9XkG*NXkfBqN7qhoHc{(fPv!)XEypV2gd2skzzK*)SVt)ArLv0` zTyj}5qu4w)1BPCZX~&Qc30V#O5b(%%PUpe~4ufr?MOg6}`2wLGYKd|7=?54N{kne^ zU|JLJB&{?^06Qn0bqk4p|Iel_-}Fgvnh3k#!oWN1U0#>zocWM{rTAc`6*@Vm<9;G` zFLKZE!`OLeiMdc#-4-tYvv}ap%Iq?i)1?a-@9Y_TofK(TqWl(*veclg?lawHV{YyW z?ou?@<(|`6uSU(ysMY26e~ixMasXRZ4CiC#2WX$;A?tVk=y^BbtPc*1cO{6^9^yh}+Mn4g z69jyC(~%OQD{78XK*Kl0w85b_Ln7e2)NUahX}W6EF&e?zu62#^Cb3M?P&3;GWf~zx@N>Y=AFc3O(SxYvUx9z``GChyu2jPd`FhlH)8HGnAOAvDU-ocSC5v%A#vF2Q@&=0IAAKLEk{iB~>va3BjQ055Ie6%K* z#yy^Mzx^MDA;dC{^Ev@r&!~((&rDMgB;(i52W}#ZJYR%kF1P_gYSyZ0GkBsyme`~d zqEHN<5VZRVL*>E4QtuaippoD3cKLVIQ&)j;{mR^}z}s~xvrH)f;$GirvBpLc@DUe? zLp=Cxby@Wxzn*e;Z_@RoqMSo~kO)hVqU^1termPN^i1aAN5`^126n z$3$7>NS3l9BMs~DwvtE6$q&mbN~a)|41VckWd{;^J}5AjK7olu%5oQaoLY!dK+*q0 zJE;peUiuJ<2NYElZ$;#EUgfRoR&Xh!zZvX;iMp{eG~7Xb!1BRSByqe>6LBWtPRPH= zr!ES$JTo&C=XtEhVlnL&wqC~LKl`2K@!!#eB!YC?>XDjsb0x#~p~myM=hn@y-TnQ- zq*A&emyzXL_kQuoZuiR8s-^V+Qv9*SB$|^9Fj-}RYHISJFT}XFXq-3ZVQX5}32)1g z-_M>XB8dC>Mj?extX249MluvJHbVK(9Ti)dX~O*sqM$<=1PM2p+AW;yp$*rEoWx%;!Z!UHwJpmZ<$6a(UwW z8ZAW$0F4&+H_%X)ysO6)evKvA4NQY^f z$;zQ%3+p&TeYd5<6mXX*bt7&B-Wk$Hp*vuRC^dghOJ7GCkZSEpfG&l}WD!3LkCweR z%UyomI50&>QOCopw_X(9QR$)xg4uG$Y09o?EylxuSvB5e?q^N%x-`5)r_#)3^n*`s(X9o1#(oiB^_@b+zSyVrJ3Oln|bj3;WzB!4%S9W{Dr{l;*3K zP4dK(>v=^)qXGb}z4X0GK*DhqZcBISpOvA9uMq}onYgCEaP zrrdDlijAYXyq;D$SWX()$o9uos84l<2g}Axx6f)B<2L z1Modannb7XFeJR1&P^W>j22H!4#cziQoF$gY2~E~)7W5N1LHko`%DfhpI@%bQEvUd zSMvp=0zmmZ{-*O=tIi!9zocd99U z(>64xeUpE0K%l52D(;?`!g{CBfst;v-DzyaXLjbYQbd;Jdb2%x6y3#`hqJwk7Fi|} zvSks$$x@;->9g=CoFuQ_LAzuD3`Wgk_EOD1eHZ1UM2g&d%Kr4i_|Oxw{MN1C2P{Ab;yt9*h^a z!Phe{N`nwQy;oR}^iXV0ElejGjSO@anRz?UYcMVCFF)2)&n@3Xb6g)+G2QPDK<87U z{y6lrFs4}>YC!?h*n;}kx@r8}v2#N3t?uXT1^?7nPfT~-e)e>akuN59V0mJE4mP+r z?`mH93Nl)C^-IbrNz?G~nx<|txBNo>YNfe>+@qMX4}+l#lNM6{TFUoBd+cg<5fVOF z&_u#2n=NI^75>!f^?_NAAN)OD4ZqkSjAl+m=*OL1)mF~R>oP;U#+Hxq2llYtE{64B zDCV7K=;Pzs>?MqDTHfe}(7Lhm+WVFRCXd61=_bF!=FPdC)ArPN_rN0k^WfB`Z1~nJ zE^*5+fpa;@C0q`~3FEfP!v<(8fL+w>fqS}@)g4CnbouO?2K`-tV9=D9gi`zRhoho7 zmyd7^`pJ%o>iS4h;nIlGe?yjLHnN2Y%YI$hAK*r<--+v9Is?d9MRqkW1O(l`L%|ZTDAtq^eW~zXeB`7_3>Z!!{;r(sS8J(%0r` z@)sFPy;1iR$`034l36+{(}r&(>n}I%-9Yz2KuOsYP9p35b4c_C{0PY{PC)=gi5i1Z zQ+>vE7okeD5YYP@zpWL2#mE!lU=F{2U3DP1`N$L!MHU~j0^nF^ASq2IV69=dH#aA= zR^Bn7xuL>F4%W$eH&JUrq*ECrI{@cvcvJ)1i??m+-AbIs{Sj2b&IT9HG0*dDi9TQh zPk)NY>tepDl^j&+XP^f{!SmWc;9W1l{$z;{X0uW{KiIaAzuRi^5u@TzG9i?DPOLb_ zzxpmrZLj4#Mxye-8oDb4*Y!$i~o-@{gY|+|#blRcpe(TTx@A_8s(JF`K-@ z12c#3KWL}TLQOT<@Is@+O%3j8E>5L{D&L);>=6x+MmGHxe zwh-5%55@uj000000004Iy;aKNqKjwMLCLH4;4~H{Kj>K4FGm0!-)mcMMAppJC4d4= z)yvEC+NzA#GWX;z%eLg_0T2S2?*y=7Z_b}R_^_Ms55APJ?5&6P%ij*2vis?AZIs!b zRg#H`$W|`h9AsTqErVhO+RS>EYL1xQj||`d04pJ|Y7YgAA%Fic^y1`oU>uj9=U~%5 zF!1U&3bynw&7|HK4Qek5HUKgavljLX9{|s*Dhk=T^9bp8(fAi@jTs2vXI@-na~C9A zLv}J?s5(|Xrs@hJ@fw8Sq*-KY@F)ZhMnvQygB9bYVj4!1XPot|JZD$P(1>;>^Bhv< z1ge9af#|Z+HA4i)_j81qXCf39dgPNY)sh~F3o`mP{KoE+GAIf9IP~;7x5Y zA6f$(?D^iI4tGX02TPejC>5WLccN|2kKLJ9wvI7 zD&7W9QWoE8K#fdaJ%Qt8R6TKe1)wUpGHhRc$T7yMApY&?8IYud0!1AnQs#UH847U) zMsEuXn%B|aC@DZM0V4nbKUr42XpIz&fJPrP{U_&W1_PVRC1&Ws&mn$@kUn!?98Rd_ z?Q8Y%9~yCry3XxNm(QecFaUUcz=T^_*3@Ew@DJswYxL6iWE#5C2;l_rgaMe2SdMp- z*RYLt_&X+OzCm4G|^n(9+J^g+1ae z0oyIwQWRQ!AS&Lj@We(PLkC@VS(1(G6}D26Zg3{ZEYc^GLz{!MWh4;@*KDmS)ykz? zTy2s5W{PsfceMPW^L6~ZRTc>LzX9G12r7Z23er^j2h5hdTWvlmp_8smWZxX!8a2JU z_tg`XevRgf?_L-JT9#Zg#-Snj+TI$Yv(pY^>Qh=)0zuOB1F`a7=REWas46>CK3%HR zcYsfu*{$?L>WL_Bs+G=wF|U0x8K#LqZ;AGma~-Gh@e@uL1`v*0=#v@egPb5v z7t%!$2AiOPnP(;buawANo3!x#`gadc!dq~I{m!=;t(4V5ar9`LtYfg@w!#L+kd|ZK zC$yygS~yTPh9Ik{&6%O)3wfNQnxpzji{2saUEwSnV) z4eXpgC7Jhb^PG**XwHXc;vc7`FM3b=X_sb2z0o%7QI-5BC35kSmhz0Y9JEy5qW)>} zs+;C{MSWY=|M>|ocAKI%o2}*H-5v~!`RET!)tSQ3DD291&%WsG@=b?+y_Uuytw*z)!+jX z-AM&>B7(9@<~niFa{M-buKmBmAL|kr;X8n958;Fgyu7694XM^pwxQ8{}pI^jR7+HS9z^P0*-o0x~rcjdKjIR0?v`AIu zMlo-7S0vr-Ch~3>fHH*N>ARIF_~$PyF}0I-y@~jWEGpFGfq#FbMPk$hAmqkpy{;OJ zD|E)2QH#jtt;t_6qO)FS%@XmJ0TvtO8Pgu#(w+b`h5p_+1=xz}bB_P*PejZp(k}-} zL0j*0pQ)xTM=o*&g=+E+L9&>&08;dX_iAi_6p&&;yQm?qF_D}e^F*-UGD7orDksdr zd=&{QS8-x#WOX)9`y$P^O`tb^XqAeh#hmy}nv zby)jzZZpq~K4eCf{20bHHy=jgEpp^(O?(Q9NB{4%IK7e5P}r);Fnw7XtpwK&oJ${; zJW%N+H<)M0#m&>m?}Px3Ue+v!1TX_m`yRmH!jBF_K(4=S^^WWcT-(h;TdqbS09rm; zDxDM0=^?s?Q#-&1=tfAd#o;E8@rHJ`?4!AQoq4+vZ4rsj{dvBue#w)li6E|S*+4%P zyE6Qo8tDKA<4!9KM>${5F=XgwiNs0Gjpt+I{5O&*OEU33GvwR+OF~xc+ZQknkO(nd{B~it5wq`D9>E0@*!%O<>rIpS(Spw7USZw%%B7IunEXkK0dRJq?e%th;hiYYx_>^aR7z-mrv zoXZA7HkZZmhCAl0A!?V`4}Ls`mZS3DKMT!_9;j(xbDT{?`s%0qwHF!O*dCGHDp+t= z!pZLogvn-rFA{;SMY&I|l4|SD@=Nw=#P3pZ-uouzQD%u(D7UJAH}MRjAw*5_FaHce zni3oNTFp>LcmmWD4FL2)uYcbSH>7mwZ5sth!FXX2ogMPcHKNiD;uoc<%tX#GF_PBJ zDQ}&Wj-W}lf-oSa64{K^V}@6)}o0ttK$e2s8#0P)j3zjY|m9Xt*)KeHQyf7gySsQ z8mwkp9cI^q&Zzp!try8?94b%Z;y`KvF^*4_Cnd`&1xFk%B8iI%;!zAk8jG_f^Q<2^ z`YmvA$828Z&I`+~E41qLn(s%s)YYRNwZs1qggIyG#!{~aKFQF~4*&pHFNX;aAPq83 zMhje(5whw7hGZWg3xAP08+vmgWJT$!+5A{PGT|H#b?IW}+^?|Lj(hwhhJ;y9bREJ! zGhn!e68p%Bv7*aHL)D*_#M|C~0aJ#xgS?d@rn~9#*o}fHm-A734yRA8=zCu4{w_ck zt}P+_^I@&F$hdty^EK00mlB2iAJ?q7DY}qT^}oM^>E5)ce2ZfPl%a{Us{AN*TY)gd zx2Bdt6_hf48vO=0UR&t&^(A=&aQB4rFEQ~-*hv>OL#-IU$$FHy|HJ{MxDE~M`$O5u ze(;tk4$?Jn4y_Fx@In74-q z5x3_QHccFv4M6Wg;vjodBE`ovLJ`vS*LPN7wC9961#K-hD|2mP=Fq|L0e0Q@=yLgd zTfvf+{lxWuGCTIP&zt+ux$Op^&2`AyBaQhH`1*9yLD$d?7AiStcs0t{^2;`BD%M}oDCVn2eg(U6r^+3JQ4ArKXRC4C!Zy^ezp2I2vBL5uAOMYvby{6>&FYvm=^fNzNSKHe6dXyzJ62Ahqa~3be4vu#47mR|&t0lOm3|nC z;soBm9Qs~n_HIxqZ<}JnGO1>O_q`5`;W(>lqB^5^T6AmNo}F!;3vvsgE-U7?fj}1t zXg12Cs#WhX+DR*U2CjR(1l!}@k6JNFZj~(qkbf$+zN;>AEqx=v1cHjBF9_*RE?I2w z+k+DE@4SJu`eK0#B+qDU>6k0{H`xhcR`e#&3QwCUQ|SjjslMW*>+8)!s7@2YU;t<$ zxEi~e>y~uj%1GlfSY6ed_PJLaf+;^ISdd)mqG*HRbX=Z9Fv4&P)|k5EK_U1Wb>ha_e=Lj2 zhMymec}W9JZXq;%i5LEY7Zs7)FuZ8vji@4;FZRc`W@;UH*K3^ZOf1;8*mC2Mfd}V{ zL?jv=FWnhx7uL9IoUex(w1Eab7ADagS{i4el5vaWEs=_NY7}cr(G1G%GDdSNN_>pU zBOa;n80}WzQ}%l67^Uzugh7?ozIGBCrClBZg_IIR7yH^VO#7;D4GdqNQsrWNoP4%w z%K`7CP=?mV!Y_e3)}j~}dAGPV$x;e*c84ctp=7=SXOHf?|FB3s^A3&#i?z~}(vYHV zlD2nyt%BIVH9ZI%^Iwb)g!>Yh^VnZtm^YCqaKkt|gp#Dl*l5J%jg`>=0TXBNIJCM# zvh3vd{t{{4#+;RHFsU{y5XHm~btq+^{yug#l7S!B{mcQgi)Ri@wEDi&DD1wz6MggZ zUoMt;9reA$dXA&u&DStoH$2DboEszA7cXx=Eeh!EfMg#iF;K$E{9no9baAGELTO9oxEPKxl2((d*LgxdhzfO#?%FXn#-@;@PF(7fVF z_kWuY>zKJ~2;$^9tfN1@-2qCiy>?0wru#W4QIuYemDwvkh+!(*i#669lod0a95VD!>`vH#+)}3v{?LS5SQKAw(qngXK$*AKI+Iq>!-lal^*&Zoto%)$} z^@>*7Iqt;u_HF>o9%eA$W4oo&n6#*V^lW9 z5%&Nz+)wdxFmzm0Op6uiKciNn>If>tFUOoWA&HA9m#j}0%OlWMOi?^urF!in^|J{vBBEmmzhw6a>Sa)= zx)?I9aIp%F=lpio=#GgJdWeV-|4ygAxPPJH2$JPQ77j`lPtH9k!_q3?!AoI z1nSkYY(ii+#h^qHgc&m3Zk5AEJT&Gq+eA0hFLZf;*SBg{O8NBd-U8TkGg6gg;D?^b zzv}1}T>^oTWMI>4pfppOa%urlDI_n~I`7UbE7i_tH3KLBC~eh4x_o`*P~U@n3U_$V z_#4B~N%^)1!wqrSj7V3KN@?z=z{)ogD73+hPbfYgeSO^{yt~_hi#^E zaanF7%7TqV)Z7uSVTBo&o{`V3iN-AmFTmc$H}&^OIp?k2CQEcqGhc3Uj?I zUQW|-LQ0kWK`2Z zVb2!x5AqqX8;BGMU0Xg?ljQg~lV@n$3vw*89&vHL?KaY68m6#N%#~k$ll7COGgtSC z@$Si#b+5#NZ>vjY-7+tvnjdSX*3(of zKs<0PRWg3&7@K(TlGQ+Lm z1iz{&^k&>MULFFNxxvDVPRo76yZ{17v;bhRQu+72P@#n!`2Qo2?bg;YuLEm49?ax$ z-E;u9e?C0G6?Hz>iGTp( zXcy-oOL}Dk_+H5u(y3)~kFTAW{(uNj+roT6B{~N#%&C=DJ*<*f$3orfc?3}^9nR82 zp`Q`+{P1HRwNP;L{+xl2mI(~r-xOF(E{DmKk%SB#DmbRC!`nOG-MvQe$sj>`LDo|H zJE3+s<$jf`!8gX;sim=9S*j#}o|Rd*0UAmNSq+@4B-N(yM+a6qTDxi&Neows5kWGA z@mTCp`+|9q{wlFboNO<%;8moq8=?aw3tbx3{r(O62f<8?)vIxaID};FDCU%epclAK z5KL0`9=De4RE}4lC)~WbtCZieBH1&G#hxoWtqb#+y8oWUv+F5N52Ni(q2fx45v)cV zVa(>yZI$azTlAmN*`t7HLgpHad2x!bl>6pn)dMSzBI)6=0HDX75Ahsng5H*%HoeD+ zB&HW!Hfrc;Vd&Kzpi=$c=J+p#e7vNjT=oF2bQW9#UybVY3vl|^m`gJoqsyBHUv`&2 z+LMu1003qR8)=BxSDH2yaOuOy2@beDhhrV)lpJ}Bcc;?vjSTn;S!I!5v9FjQ5K&x7vXGJq)G4@;^$9^&BF6!#Pr{Vd5WqzU#9r&fhEBq#C z{8mrozT`Vxmhe`*3_keNkiJxlolFAF{WuPm;YX!RAX)fseM?4bk!S%a&*nlcc|ZCl z!7PL_#0V;LBFSNgvpCnz7#L^WSoiYA!ORo~h&knKp0%1X41u{02TJ*>(-3vs<2Nf0 z(5E`{*h|}H`gNS0;zt?%*^`*K8OF>5TztOew|=}i+hhXjcmAY|mM0KM=$DWhv{bA} zz*6dqdHDE3q$0H)HM5MuGEp80rdMLY9$L_@{a$q``wl61ch-L3UrSZa*A60@+lqc( zN2EI-D^|cFk)c8!Hd5lv!!j+CD-iky%H2X*TssPVh~p)4(?pdsJwy)uj$wo#MtU%@ zIDZrRNZwJ*>aj0TdW{CIE7fz+E@pv0RN9I|JQ<--k46?i0000lo8~GIW6v*@-3=qV z?n&m~dj*vYvp4e4WO^8qIRar}+yjN~1KP^cjRn$)5DB;L3=t4YJ0ogl-U#5>(CV(WqyJwWh2% zm2xU+ibMydw^Zi@uYUrVqo6XN3URo^4Xg2;xVvr@mD&M5#6d|nXI|`HIU>+Oez0A! z<-&Cf=f$j#`a8oJxf60TJ33gL@|o^xU6nc8p0EG_09w#MhPV7M@H1ENhjb9K2P1sEev~2hw9`-Uwp2(GafkH~gGS`!pPf`O0tXQ4|%~lUAVax*BqIupQjW6>w&4Kpy2DCeAVF_7+b_MvuNJA+7O6f^Xz;IMvoUdyy$ z)lTMLGY$(}NG~8Hn3ts1OGe|z1asfg!iDGp+4_^12Q}j3qZ{vNJQvfatKfh@{?sIt z773qt6N+Ga;(MY?D|L8FoR9rq!wVMkT# z-Ns5DC!h49(w&1CqqYBZc0-&rRA5ZM$^Yb%XQyqcw#}hcYvG_+z!LW3r+1U!w~ zpL`fZdtbbuC72h`#fc}**=SH$ORil`CtB^Wcl?PkLLOdtaBnfzkIAT@pJDv5K+fW5 zIjlNfV|CVp3x-JW*5N;;rki%M(7gK=gP07hu9|ry!JgTA39!l=OHYG7Y{vn+Yft#{ zZo;`k72UiGsfNU#t`?@4kO-E1(uKaM3AbgAs&vW744`j>%^XeNEo|KiTWl6gv0a@3 zm6=H=yu9?c169t!nv1tSI{AtC!p3Q|G}F-;td-z;lSO1a6QQ@0YhhLR3+!B&l`Q+g zeROBieE0s*Q#h4wz3LFzK0-}V>sX*1toi;+-wS$WgNG1v?i6?FSP2n|(>nMUW_rs| zu7X3zBlsYIT7ms2cuHRF(^FWSEjqa@&}VQbpkvXO;>TklFc)&w)!gy1Xfv`C1`Gw9 zLaCZWRH+X@P~$NyO0ER7i3)dP&gaMUo?dPQzwS43VQ9#~nGoLza1WZI z-75890000)o<^#5=xwWxZ*d+u{Um~V@c!FDecS+ZPd3`8EV+2gRj(bpvcRfz8@?l# z=*QfH6-?Vmp0zagr-bfjWk;@p0!BfKD8ebIP#7;#Yu_V_aWs5bih4xsm~v>+IOkk!`@8a$ki~ z)uiXQ-xgmK@JPJZh|OoyI!CAhJE9Rig|nYjWl~5CUdVUc-I@>i=0`A$39{QC;6#@@TUc_&H;ON7i2 zXse%xQibA>AlF)vL0J<*&yJ>LUJ9m#6UiGChb@Wqo^}g%R>wv=dhE2}dsW4vJfs@S zxe8pPr^i{ELZ4+Kmn4g5GZdCNbw(mWiZWq(X;I#eOZ2W9gGC@+IYrJxgR4DBDff;= zirLR;QudzlUT@w9`_BA-;DIx14BJ_7DOHD`f=G-+^9^X{xS}TblH_r5kWFhlV{S)G zYDqpworsCxC<0?$)n~b{yMxug+S)m&7s2LRtE~o40c*dO6XvI#9zboc$ zdo1AnO@mh4OtIS*N+qEHX128?<<~=p1%YTfEUc|5Eg#;BQ)8$|+Bl&VCyRVOb@-Bz zi59h98a`28_+$kRKjyby-;Q0r@H^-lfX%;fqNppA)Ps_`d8Sj8^hayquQVTaLT}bY z1*hGLk(?`=l_)zQiRv2OJ;V14xpnh|1kEKr|AJC%0#YpraP2b^_9vYXuoPuVKY?Ti z;)gWl4_ti#t?`#O*O z(6s`_Ff`@po>2~N4-q-k5~@WUd?~l{#5dQ?>D3jj9#AP>s%0gatD*)EsJWg0cI%@_ z-xNLXr`>ifx8epS!`R^8 z)I2yOxjsUJ&aaZS5`pv3$SGr(N7Z7@w2)1fo^8k30Cdi=hi^r%MB+*9f{P7?{}-lw z60AFSI8?T8*7!=+PInLqzTKxBx$*0IrY=1kI{dAgns8TiRz2Nar(4}Ty5Xj?TG0vh zICW4(vl_H(ru$Tmcj{qtiL==p;=zQXgu0*r001J+NHk@@```mnz%3V6rs%*4{UnYt z=2bWi;1+>ogrtj87uBhpyVoczv;1*AY2_H-5KY%bGqWB5o{bqm!kLv!_gc3GTa$q{vnSZcGxyyY=q~Jec(XPa zjEzf8+FB4&_G7qNR3n~XW*j)Lh~2YhYF(Z>(|={dNi;TC`Mq=Z(8Aig4bY;Vyx(>> zs8%cxsF)t14-Ag(CcjgrsFj&X?>uJ419}1#Gt7_sHs+&2E^*UPaIn#Yjs4I*sS3~lP5B|aAEYPFo#Gf>l+b*Yxi)cKYh+VDjX z+Wd4`V|CYez9W%-J+H6d6x(C@bD3y}iacdppH?&V0ry%F8uS_SCuPoC^Na(crdlId zC7b0a!HDoR=E~laR~?iWn25=j)HJ>#XTqP=OWMa=kzGT(zEARyEV3{F00Spu&uP-t zpEiFZx6_-jR6xd50WfL6Hl*2!AZOrS^`4Q<^8TwJ03?UkMP|cU1gSKJey@(nJWA#W z>V92nxzkF%{^F2-!;kWpY?RSFhzq;2^`i3ZW?d<`&$np?d)MGAAsv?OkSw2c?nn64 zi|}57VgFEmS@u`j-bJFXS~l0A9cL{NLEwInLGCE!_g*t8uTru9n38M0h*7~`x28Qj zB17GXoI}u1$?9!OE+@LAxt#>MdiHoqhv(NX-=37L9n(4Ys}_0rB4HVsG>u+y0OfLjrEV_0mVBdNgbun&ZQi?qb1YbvhbKASAHWnE|@x z^N(kxY+c_@$4+L$KIc{R`D~LfpFw`MRDDEcFcQ-E8l&^(I5z-Erl|!I!An0AQU!0q z20wQxDq|0fI+xCF*r3zE<-9KI=iE-e*Yu1G^2|}n(KnA8HhV$@4A2#J@3wq_wFxFg z)S#R&G4VN+gP1fU0mIt(XC3G(!&Ux24Zi;xwY2$=29N*%08`R3-k#td*q$WWo^_oU zCERLdxWcqdJDbMumWX+9Xf8O9z|YSjuLNlzO>nhM)*=2xJjnkNol$xaklJEocvK_X z_ez!)j{HpW4_j6EUgiokxl_TduDJRRqwP*jU);#rp+& z`|!wO0Rhod%Pm?aR;h3;I12FJ{^*OxJG=SZuqUqoRCP5Mb|ke$emd$ zq&%Fs-&`v4euGv1O8sak1fQ^VXD_=~dBP>OIo4ptNtPW|FRQy8)Gejj9RLUg`mv`L z4M*OHH^gKHB0{d|c3s|k8o3S&%Z?q9#K(;5nSl5qaaHl!Y-FKK5##{;_7C`dbdi6c zus~jz!JjxzA`pNBk@>29J$ddLuZDC8^N!u3BM_cU?-%1k0xxVYKxy$y zae4!Q!T?2UAAj?#@i6)W6=ikDSO|gL+X-=-mFho(K

nrKifldf@Ep(43Xih(t2cy>z8?*fUYGm;G5B10H>%Q(5NzFqle}tjZegtBT^k#$P^GyUVfb_*+}D zlzgF5e)lqjGb2Q%m&Z4%wtZ@}g}o2X(|_(*wi^I4`_uI(t4H|ei z%I}%oJ39fmXK6&--Ha2+@DRD#i9l~By$1}#7&7aidBH2WF@oRCm;e9(GUnO(x)~|s zriio-4ea|v*~xzJpS3GHBDg*nE%F8?Q_l2R8O(->cfQ@J$T+9!o_5bK&Yv7IObkOR&0-hgh}TVDE#)>!%9))@R^1_@!(2Vc z6fm3fqD0alx?`jKVer&Eb}GRG(!Ja+VI#`UAl{5`4KF*KL+CtDgTzGzR>CsjPR6w@ z*Z()Arg7pWM$S1){o3zjCHE>kSb@N|3H!=ql)tVd)EF{KRs|=62%B}P(Qy*X;e@en zDq^b-t77`QngI60`70HUrYqlf13qKLP9Ux4FJ08f8qzy>dZ3DCYu9buL!WFQfWEh%5Ce;ok&6~92XH=&V7iGkG0zS#sJ9E#h z9_Coyp9UAhYup31YR)|afte#628ZEmU3YJFT&o6_`ntGDKjrDM1e9ZSp2HgulX>H0 zOKHhJUoqb?jssOSgBtb!8Eyf@Dboewen{}v@IQ&-_Z-My8vp(9P~^7YKlJ7gTQDbk zP4OUP0_m>Gi)2BqrTw;ww$1K0u_g~?7>be%{y9)RWrPeCWsjA=0q5@!?qolpR=eYW z19`gWFQ3stUY-hF5mXESuoToKo(TLjRT+|XIW7jUy0jOckmB%?^P8k`R+Z4l6TaOy z&RzX0^k18#gl!hOlcEFVP*u}C(Ri9Ob%1>@zLKWUyj1{Zp^H<~i!RwJ#7w&)A)_6U z)T#iZig9EEHf{b(H*j{P4Z#WzW>jP9Q2VtG&6biNWn7EZH44TwR~BFuwT2qii_#%N z4BPy;>B}HC672pA;uk9OFDcA44@uSF;<22Th-@Bi|qx1?jcrP6FFW;vIdLNacONi$7$5zCY5JA9EN#YO} z>$3b7t5sL^Gp?92@>kg@v2Q(4z434eYG|Y0L@AbP1s6LP)+bX3i+kJ52(d-+*JUjK zwrmwYK725o)k|QdPI)qve17%apy$Wp`#f}b4l54Ranel04{_iP8UNgYqE0oa zGWDs_+8Y|gbN~PV001G-#A9A`;PbsV<7Ph*l~0O{E{(&nu)+W4#lS{(9AW&yNxlE1 zAi-w%zYkHJSmao?)K3W};n&7}k7!5iS$CZ*g8>ed`B0K0x<@&sjq_^oVqD(^2}OwN zpuliP13$p7j2|ufyIy)%E=1Eu+zuTr;Rk)o!V7J^ZZw61cLn!!j6M|P00004XLj`) z!z6(P=?7U$?Hz7G+@RM3&dS%Jer+c3z-v)>Nw5KsjhMH5gBBrDmFGh0uyq0(j3k%m z4wO7k3YMz54od^x-ZuSVj? zFiQr_Tz7~xk!_SMq|ld>2#A6>b5bX7KHkVZ!`Un&^yyoZ0C6y-0xJ$em8*QLA%QE) zM^k%h0C3(g)zisi<4f^Xky&M2W#sx1{CBA9VS>q*0&Id|<%?n>d1t7&raOKwF2qJZ z2RwEv>}P1bdA9z0o~_99=LhsNb+)36Sy`!yy4p>+vQ^0G5go4m@Y_$Lv3$rEr9Hj+|A~>P^s_HKj)dD*HyW#^ji=m)g~3 zPVe|x(iCaF2Pfu9eC^PK=0)xwH#~)9b~}9a6>}BBrZJ#*kJ8kz&G6`BL{&ejkgW8X z%2d#x+U~YU=##yZFM^e?+pM2J;>IqN6M4KV(Otd$fyH(RJpa1m5cRY>#skeMKQhdw z9Mk@pCpD11MUVN0IXI9EJ=0y}@DmxYk)-wALm?sP@ewb=l$6m%dm_YjL(7>Ix-~LQ zP;2+iZko(~vOfM=s6|IqPd7lxuCk(!HoeNLoMPQO*rUO})U_A9RmftP-)&ai2!*ovSwf|M%hIACZ9;eFYb9!n&l|QiZH?mFR0;XwKiN zIprEosD6C@JQUz>ad5ST%463IfAc2x(EwuY;ZH>r^1&q(1_MKPbn4ev#0>O!pN-i4 zn!nj{Gm!M9I!T=eZwhDwiXiuIUaA1Ahp?K@f9H6q4_$5<&A;7ug|>Kbj_w5?^6c^@ zxR%`};`KkHZ9=HKG?L0`o6ECqMDGNCXMSZOZ7L@vsx@+nWEE zirbk)9J91gKmo3_XL)Zyjd$R)aPu6#tQ)&JqP3(d845(lk)wWw$H2OKIcB%A11=7s zLwX}@ua_j<)1BZv5bXZ*O=uFMFq*c}GYShWVrX16#c*jgeadr%_{y3Ot3Xkn+2^=T z*#k2(flYjYcU^h9(tB9hg^vEB+*%C+YJXdwyNmZ+LZlN0yXA8WL!?|4E@S`h2fbK! z>kLf7mc7L$Z=Y7eDX9EoydGk!bb4iYoFXz0`!bNf{uqS?HPgc0hK5byk16`~EU4I& z_ITsn>xDnmBnzVHD+WWK2hX1lw4=Cf=NLfGG4_)n)wf{w*oR#kSAS>$bBa zbmX{CR+k>Ns6gZX1#8JZjL*h9sxU_p`kNq*aJz9*GyEEDj3u4_)kg1<%QBVW+Yvzk zCI&J23m5JK)&h_?uP{b1$Bsi|F%msLnV|kA=!lq&w_cYe8-q<*PG8w$3+S_`8eR{o zT`rMECJ2inptye`>Qn|qIo=^c`NnOp*sFp$Y;ghO@cwIthopy{Z#WjSWO<9#EuDgd zV8Qkb4kwy9i)bZpfWIpGUXdRx;KmUEpATZ7#!~N67Em+F*G5-Q2hG}SjADLcVw88R zQg!{pb{%i+L2$#JkO^5A{k^Dua{A>vt;S=tPoF8j#Z8DLyMmMKw`agrOWizOKL9H}=*l7zgHbH07}xos#xeICnWXD)z|=XxlCHSKDtP zfv#0|0!wkK5?M0wqA5nS53I}3I$VG`o(ymE9WKOqSvD-s(xL;0nl84b%DKJajI6Up znGtNPSV0c-C0fTjIOINg&Uo1;q+zRMFJ0qfqnWdzxs}ezj!G~IT`noF@`(+zIJh{K zwh{p6_`iz6kfoLCc#Hpo^X8Q#S+FfFBZe$ZtI2ARd>duD_{9*PKFUOS3$UTOE6Po% z2rBK;NIB77H#h$9V)VBWk+u%2lsycYl_4laMsCU7%6NCzdbB#5`8InE&68iMGI>bS zk;IzMI^i{n@Imu(U9BhUN8NJkJ0m)I{-#a(b+u!Y{gG&x(ZBh&JVHyx8N?ygO9dT&MAe(CaVy;<{Uj?;ACxoe0m#KBdrY} zoLCN)S7O$Xx5qXRpM=Q;&KQi0vcs(jXyAcNa>SibklUPlm$-puLjK0Ozn9op{|eFEs#sL%)*ngY>&7wtReh##dm zbE~dO*#42OkH>w7e|@d>Jx4g7X?H#fP#5N*x!w{p17lXmL(>}K7bsV>S~Z#BJ;3#K zETHZ?oRK6t#>~P@?@9j1`7mG^qp+l~Ng)Qt{~S-7E0yxxKL(~Oiek~N%cX6QVTwzF zvkzVgyoaCCI=>*dTH5OoG^|J!wwa8FpKQ3}7kSjS9zELMfwZs6Ik#7zmXQnJj09*S zHbl$r6aiXXv{O2)>_@W=2(UM-Hz>J-TzxAtgOA{8ys#(ez&91w!^m3V?Jwb+vg_nq zWo^pK=|b_l5}eVWVZE@a1=>y}s~LVB5E*n{$h|r+1$#h?-6be%{)bjkiO)v2XF!EH zB1#f(+BNk2&F*U^a#avEJbvoxlR}|rem1_$6$KVoaSL!g!rWOhDhna!Ltt5sh1zD)8;~exzw{$A+6*tDE7XH3$51 zckXTILW+{P#r__Jz^_)7w^fc!iEYe4;)&gjJwxZiv}IT26HT0S9J2a~>^;ulaAg>G zvK4n;Zvke-sG26@M!X`fm%rK41eUtny@Jg;Ug8onZ;Zj^&-r_&_kYv`spJlCH(1)X zfVAl6*;w;nKq9A?Zdwa;`+m!DZS%r<6M_VASTn|RX05dX_Q9_I4uVm4_7-Rn{f-Lm zr;E{S=OiSXz}YH=eoZO$My-ydLI`wfEk4_%JZ2#Lm&eLsn}fq6?v+H*iw(fBxh--d zx34YwzYIFB1;57)bT$g`+oV^_b9__=&a9Ng*)E-Z%4g$+ois|GVaOC`|4+A(9J_Nk z%CDRZ0M5nmQqiy|U~2QQO~n}EO=tCB;nkVT40W}hS-#-!J=Ca{G>1d&?;`0PBEv3 zy*96h6zd0t1>=M1u>{<&_kFC;eI1BX@NIZ>-VL2JVR>STe{me$wg+Yl)@B0-FqapN zoj8YiE_GFUJ4hmka#6PsFS{*NNf=Hw0SRml7YIpy?RJ8!dRtj zQ@8vQ$XW4}hYq9|K~S=+o)Z4WqrEMyW}j#FXwsZw#Hivg(kt^T-TSzZjHHm4G|Qb)C|{M4f1^Qm4)vhM_W=YiT#0{H2@PiE~s@pioH5i2rkfDO6RkF|ewU-~ZNgt+39>C_x&Jj3w4= z3_kYKXAwKlxv7Ndz_-XrA)h2aNP5{mIq6Q8m>NE?dv+LPZSs^*V&`361$E1P3a+E8 z6l_iMDX8EI{TXaCTwNSu((t>ZnpERzZodoO?l_2Ug`)cKOE$rb)wfoz^RFwk>crS# zE_^NBDkh`0{$eA_uEP3i$C)ZA%25O9T)P(lG&w*M5#FD?PHHbVI>Q!pHt}$7@H+6W zl;ljkf0B7Gf1T4w&<FD{hA2O+ zPfC!@(Q&KpU!zNnr@UEifPL67hi!gyoMa(?-s`ZrBj0f(_4_T(k| z-64R~o?;DzpXcPY=2ADSV{(;u1}$R;bMfh~QgT4dY$?@^y8y z&6!GvVJU7>H6;(bt&9O(H50C`M$T?dVd8Z9T8y;l%m2Ij(c{op9hxKZL#Uavzyd=- zJ2Ns(xbUN$dh79%Js*(5@Vh8%nSG@UHJf$M6IA-_-ZN&X;C4$Z8+6=LCv zM3E7Q!m``#Ptwz+LO`nL*VVGd)KVgt5OQsG;pz0AQjZTd?RjB|tGHQX$Y*)78e3p2 z(+xCFw~Smg___Yqx6yFhD{4!^$H$e|_E@+B9tH@r7?5`L)6Fl9BkQ_jPsERftX~fn z31f+`nRrR?L(9wA7vIpgkkN=279Bwz5 zle-`-PEA!ZPI&eh?sJY2M6L)3GPu!j0rA=P26gjnGf&Z65g`8N8x{;(30Pmat4$OM zsFK}jjdmFPoGr`pEZqB$g-BX1k=WRhhOoMH>2n}6Ij+c~r$*R!L24<+b~$B~lLbeYD%+GPL6@Io4R6jpTByXKAMLndeoXpAwc z|Lilt$Bl4>U$WGnQuHoz-LKGRWH)dMb|aCal&mKI=yq0pra*S%>|6UwTA=@7-&dE=L z0jCj4&a*&N8J$eC-vTNL@o%p3`O!3*$jMl}6P@ZncNuGKu(`_11 zNO&A$jfX+%DMvqufsfK5HcHS*Xz%FOn?qdHPRdr-zD5P^C~V2hw5i`#$)~w9!d3lF z1+f5bg&i!&DwGD=XXr*HN&9KQkI3;e!u87%KA~Uwiv?iNMV;GkAWy|J-m`1h@xt*S5@E82@*aSm>(FE7G-5L(Auk_8tO@z{;*Zp9h4SAVy}R zTNSB=tGH?U*4$5hGLms z>wzOBI3K^_81<5Mf9nWVTJqS;NGKX`wH70o7Ra990Jjg-Z*I^XQi z|K(^Xfcb^%gYpP5D2DU#q!z6_B5m*4G+Mb>?lZ?3FVNhA*`JzxwMLFy?RfoY?_t&7 zwkc@11lE=MEu-YfoSof!e&*>CEyhj`t)=6|S}l51robw@ykNEz%^Oq!Ee#tPgyN+p z3t#e(vt-kgvlxJOo9mRs$g!ku>?ke(uBb!FGAY9%fP--=?h=$8^e&e znco&VhQ}q)o2g)Bzy&!WCOaGqqB&ydJ`iXLsV#D@E>%_zX^sS|_ytN6rV&q2vKNS+ zvT;cU8a8!jv`u#f#hs!A*0nUJ^fPkyPIDm7u)&4Cw#eBo6F!zU*pA(wfr)uxF(!E; zAjnj#k%H;zfDVoxN)kL+^Xa=SNZ0;Pcm-6UBjop?d&Jswk{$RZ#=$}*fkaajAxGcA zRk`8Nk*_`pkWla6If`@i+PoZUM9L^aomvlo&_`29*;T-SP}rg-TbQ3#!4?2yQTvUz|Eo5Zn^p z4QK8=wm&j|GC##uDN~Jw_IwAHlQG_cQE_XdT4VwtHiBbWL*cy+I^XCgqn30(KmHXs zF5{kZ4)s$qY7rkM1DEYjlX`if;Xr!kSDY_|OHAeI4Xil?-kSwB#DdAs1_4r(>-_Vv zE|ht5mv9I*iM3q(QdVshb>o2~D-?<9u#f3Q+;m12r~ z&xaI1+Oy8#L9Ba*-kt$PP%Ib{L|GvZpjwzh+#k3V81tcby#@=jI!*5E#UhDw0Fm}z zruEfBT2*SM|I05j8eV3wR8T@)aZG73C=}E(zX>(C>*^m)BaUYGQuGo^(jN7Nv)ghe zrS2|_*E{?3!sYW?nDcPE`EUU$lI$y3F}~WGWvT?q^dcJpN2Cizd_>H-0jggXh#a9~ zVy+#1b?!wN2>=3_)#f)MCzNlF60x?0XSO5;CtDGX7ub&D)ZG;&lG zvm9xRoR2`z14U#=4Xb>;<8Vhql2)D!ZdiZ1PM8>)YR^G0$2%#2gP|OH5fCHO zx~}OxF9-i-$5nc^uY>Ny9+gEHh-k zop8uJ(!z7oW?*G@A}t5GGMMKEUW2r%PX!-QztJNMVvQ}Ic6YIUyydeBU1!4BJK8Dh{;tp?^mm?Etd{!X~8 zie+1iZotH9({BTUsaRrW3u~*+_#<^8F9Q6d9Re zxx_dzIjRfT#6R>}l4{(QR@*h5(##}V)%J5mti&|RO}ox#=!XX}oEN-fw+ZU6bZ~B3 zCfs8j*~p{PmD7`SZkIz>L|=$}B^)#I`ief~Ct_gK1sc%HuFDo;N|h%u3wmYAy%{xr z7Gtmh;3fzrwh(+{k(-91h2x{xf)5N^)ZC(J8wx-I-bq>E&VXk*19cOg*o}>~(|b35g>-lW^xkn7 z?$rTfX>klq@)!$BB9mkiiM|m1+Oh3sgyGV?@OKXZ6+UwFk|kQhI3dWz%+ITsD0 z@HsB>JxD=TnRO5G`RFv-d%W9u7sklX{6$_->k*MVK7Ue;0?1hvh6Y z&W=4DenGh29%T(Si62j~B84pmVDpq_<(yqmQ9$)Ta+zRMrupc9tj^I8COI+ndEdDH z^}|%8U;!DGT%Jc^2_&=DrHKu{b<`on6y#_tr2qgmEF*mAH?wg)^xVXerx2P+O4*lU zJ&U@BDOq9QrKJ|2rZ~JCi+vAcsEP7!bAuZK-PsQga{Ig{osa&Nom1cfz|fcH=x2>q zh%pm?LGW-Ke+PzF<{Y*-oNUO*O=2`Lc^mj3tn_4ozo`KTqgSXH1GUCi#ZFwxUtnE< zVnmXqn}?X?>hDIVtk2}9roV`e^nU+tf=A6#_4qB?$32Xw6)-^qum`~(Ec8TM2v12Cn57z~kn1wKS* z!NCpz37+TOdjbZ#otlq0H2r`it-NrDIpB*z`1Bs3I>doIbJIEAqMHE7 zw&*vc`Ut1Z?ynb(Zl(Ra(|Fku7~F{tZ4>W&`i?h;F{kP5Qzm?nO7#v#!Xjl?RuO^E63uJ(+M>_j6~v@RM7|Q3^b)?7q*igfBP6^-g$o- zqYF#kw}Dk((Fmn(rH+I|GSsNXSMx`&|B)hY#BE=Pc{#d~-`Fp{#r#x4?L2X+=8v^O zf)^%dFt9Z3=+QkDk=2tI#kAKBT`9Xp8K=JZ%}EfM_v;Qo!eZ@9??4dBW!z zrFZ}U0000GR=XZ}?C5y&HH%h>J13^MRObY*e*&1JpfaEeak#^>69~eM_DCy7=dkW3 zec+P1lg(C*C(GfLIjr7!s7wG9m|;@7HzB!uht2gzq#Pp8sw&JZL_gPwSz27=xQkU= zXfKDXf_<(p1ar!+fVxgPpDP!b81`ISUmGq>hW1v=%nc{XOFAKe0X|`_D;K>0{B_kV zm`GtI%b*P9@8pN0#TAuXI_fSy1i8^I{3yrXLxZG{CH9vO6eKW?SN7h1{f<}D-5#JO zhSkagZn7%Dx)ty!vNDr7u82T_ekB@H zY-B^8Y)kv;No{6+l9Yg1&Vq*+bP!_`!tes1u$t5j>L9N*Kx&Qs$bGw!Z>pl7gR8g7bV%UF}!SX zaWRfmwvhJ}IU|wwJ=fr>3sUM0Fb1<&UEIw=zb9ny)Z8dJt+=hHwjeLnUHDEJX+f?! z_}XC4+&?F*YpQ4lH<@nUw|oQI0tVkju}OKF(z&cMIVm59Ka*NaqF)A(6dz-Qg6*xg zTntju7zu&=q6zx40r-S#71KXxB2qO`D#7e}hO<@z0?T1=f(p3aO?B3hbpFnhy>jxyxPqcw0*!cJJ z8Hu=U;UMm?o4x{k`+21FI)h~(6)q>?jt*p}8T8&K02e?=y5bs^d2Xl0#J|yDc7pk$ zm;j6bcR+~0WJqdXU8RA(HBxuRem9A$K}P&etpJ*KGmX;ADAXCSWA`tr%Ztem=5r4b z-ej$R?{?zZg&b>2+4Ez#wDyu(#*Ks2_)7i_oIn(qyomaFA`PGrkZy(RVoSI%oJl80 z>5T~-39nZjD^`5y~0(J5A`1euwirBS;E7d$5(Iuu~-~ zFsS^YX-YV}CBn=Xwa7^}^+ zPxn_hHteXJG<~zs-n5PA+R~YU2IVfWY^PIcp%nSaKOWPPyfmWLJ9#tH&5_4sDHf{z|H)1jE9pmKlD^MZ@XZ>_p{@pib3U_8#ztv5 zg`h^eej#+(XI-cEAdLyvF#l?=*IyC`@!}Sv20--+xF^|xGzMxEl?f4mP*FS8N?}6X zOE^dMiJi}B&}umGYd&0m(ggpt^{w`%{W2Z~&RiRp+PoK77ytkRXCwH+wS;d>k{orU ze_wQNjnTR`Fs9LniGY%?&iN2!_ybL>=XrAI2-W~?KoQ2N7 zkSaCo?3&ft?T=REC2oUFnR^1J8KRQl6+;Ety+Wv9yEmv+3>Rkg3Za7R-l0@5U7OS@ zh6}TLg;2qEZ&0cjF3su{Lj~ErLa1P`gu>I2^VxsZ)q@5nw4!duTS;Kj(S#2%;JrBL z=E2=uoD^MfF(kc3WZhH)2DydD;{!f}VPqVI!!Xs|{W`v5xX080onE}}J%U)C60v2i zS2h07W;`IKAu+>5F|o!y*kdw|gGZ;oKuU~rayHbY^%nso?k`16dPfi8x#OX3c2c$Q zVX|t~>l3FGj=tjqV3vaIy?c^uWlo~eV&z>YowZyerjpnD$x-Nj&{M`JGz2p-UFHOC zjkVWfb^3kw`^icy;bP&E!hI^Y?hu}23rkBPr~8D1;+}KOQ49r2{lrt)wX>9@5NraQ zyFsNjdf*0poedz*pUhHmcxXUu))tINaUKbp)I4UIZvGo9a;r-9&??X`jT!})rD%q@ z@giM>mMWM*Q*j3Tr*op;4#f-q^dxmE$Z1eJP2h2)F5txK`<9ZpjOQ-TDd+C=OD>rZ!?d;!RLHmcXgP(*68twT%|KW758BtFnD!sz5%P;nHVuh zAnbdmvTp#0l3G&Kqf+XM4fLk`hH+lAYberDt%C9Z00&(p6bV>d82;N=@}n&coUXPJ zqKhuZ=m|L(?VSrc6F0SO%)Pdt(fulvd<+{(PPZ_&L49A=-$=Y>X3NV*D`m?sS^%}B z$dSK_A$J#l0%KN3;FRFwhFut-J&VMA>e%xf;Hm=@r^@=u51%eJxa7o&TvZt}h0i4F z$>@0o-1_ko$c$4%W>USQ@4ePGr;k1R;$svIj4s(wVDy+f`yHCuHL|b8o4Vrm@hm+099Wf*qAlJTgTX1N zGKwtn%dh8qVZ+hBkfNYFmvd&hUNT!Pc$%s}{<}f4wrOZo;E=6wE$(wjYZsSSpO~(j z76mROFp|&!002>m!{6IHp7`EfoYy!8lQqS8WNJaTRgVoRaG5^+8vA*2H@iAi#8_-g zUmX)+=0BWhTsCWnSw%Kw=I@ZQkV@?Y-&f>NO6P5`R7%Dr=J6;rO#05SL}efG3C8kk$a%{+yzlZ30Ailn&2^xBf>}Fd;4>I66a-s1Ny$qu1tbjfaYpQ2u;|UN@p*2r zKONLw#NkoY=YJpFW%jD!KUB3x|M>eo4{ZttDVWPoss>i8YQ;(xr%NTg{(^=U%Mf*o;z9CHBrc zGs=!&#X&r17g^9AVxjnr-OpCvIrOK&)T-;;b0Q=FubrL?f=<^j{pGlvh-Y#qVJ!Xo zi6YIkspnWq{tH8seok3?14;KOuk-ihQ7!#-EwNpamwJ=sEv?=c9sCup^6Yy47S`;g zA1G9xzF2uVQ19J>wL?yUZvrD@Irk6>umWKP z-&rSq7c@!Do5bLQB8JOWHs-_^*^{WVzHN=@g~<1$bHP(?OI<~9r~UfH-U!d}WUO=3 zf0yp@AH$??nvKm?10BfaeLu@ZI=N)um-70)nPXI1A({}Jwvr2U4&OgkA8p9xPZR9n zqO9DpRUQTx7+zj<#&6fceG6PASZ}CDs?8%8qAXQgQV3_ghLd%wb}Qq7aX}2Aboyf3|}%SkG8SSMpVxF-t zUM<&ybl}AY?b8F@1$3*Q*kPE=xB$N}TBoHB5-)ph#y{x0p}$Km?#G-0ompT|tp}w; z%}n&Ux{&m;_t{1cg{V#zwQ^(P0N=qEjHD4sWmn&d(&Soj_afhx%08`fS=QBm*2%_v z;03BdFPBVxyZ9oUY?oKwLzd4Jaj7)Clw*_>V`OyV=Fn|5t_48*i^=CWU>|WUC0?`r zvB^$ZQ2DRjDoJH8HIOG1x9pJ@OOP~#U~ci zy1B#&v`N2pH4C3|8559$2=XXc2S0~MQrAw2t&#?ql*znf5x#-(*-VMAzC2Ed3znlM zv+xPSnBuq+V}6uZTad@v!-J}2;frBmqsvu}ow&!*D}5(0GAcFMJH4kAMkV45uqycT z+M}WPMW=~54eP1}l(D8cnI$Oez)pnh+mv-5b<7((afOo4KUi18M_Dvn7GoA8(rPY@ za1ACFIyOG{1ZHKs4&ftRVjS~)SR$smvk4Gn!I9rZVNZCdD;D|>l z@Q$c<2diHEgUq1}?}935qyIim7x`s{ad17Of(8ZT;DQp;EJ(yN8&N`5?s_w~fuVK- z*~%h9GCvUOPQ1gdTEBFIZ*mf?MzQNy|Ek+@PAjh(N&UVlGxJB-v^m^ym`j%W)VIxRlkuCzs)#O9xf2qj%NTIJL*;0erD2DJK?>_opNCEbg+ zjAEW@ey9Ijr{Wlc+JwF3x2eR;ju4+ zMdI2MEQW5;Ol--u7 z&3El;jpjxvY~aBpFWpX7RF6Uzn49lTbBeA~GMXZL>TJ#2-H@2dcN8;0`=>TK7Fl;AHZoz!Ozy=5r0l)= z(bc;%vl!oxJ{#=+fC2AvF3kjzPvtWtcYCveLQ$`0rzr2Hnw++kgiXfwL*%J*8XeN? z!d!Zl`!Cgb;|FnRr7qWb+3fD)NR$E>Xr|wDMuwp|;`jF4!Ae&2HC^}7+Y)Rtm5_r9 zrg+*T{-`ym+~$eyiAac}Nh-UvWdtJ`;OrHE^8nzqfC=9HT`(*dH2i2wC46M?oyec7V|J5+#soJNTryJFqcrQi0dyrLgs*)daSKuf{0b0eJ_VNDr>dt zk^LPiqU)$j)f)lJ*YW8?X|bApdF2$S(QVQ6acSkPr(!@(=!U`Q2}B4m3ETo(56-Fs z*S6FrM^QpMRhkwFD}2YvuKXz~$LX4~`a@WS%-`BmhsRLdj%V^H7N+^-4U6z}J@IAVh01Q2`?mDm zjQAn0M$ciM0v)#l9#@+BG~API<#lPW6xyk=^qHL-KWUh<9SRC6^NTxZU%7l0|MdZS zmyYNEy6_mQ;AT||V8?nebcYg&H8RXoYgTaudn*l_KZKW6d{5=Tm~R^CrwV?|%qVKN z52^8@z!&}4Rdu$4%G0V#NlG_}aNzCMHb9g9yNvkAroo(S{acw6gqwNKE5dbZvgsjIc?q_5|mdLkMV`0J^WpN2HwY1X{tm{Bq_V&}pxGpg^_iE7$8-uJyg!6O25qwLywj`y zAFvMY+HP`!=6B>)+{#5?I-p^=-K2&Re=sTVl z)z$mdX`L1ibVY$h>;S{4Wr4eA`}^^bkmSha{!SZoeJ^<;!7Ufl95Eq00W=(k`hPaN zMWJP=S`WJ_9hpALm4x%phBIc^tE#Oq(s1pI_d)lL?|RO7?L6V#eB#-G|KDYXDsP6Q z))}MtBKy*1oA#oosWiCB!6T|S6PslGmM%~ikE+1-lTXTe24)@T|gSX zXJN(9__9i&yzR;(To{qO1-*``?#K2?}2FG z{M3u?%@PNx?o8TD6!f>X-fml#=em5K@bs zGE53;ncL~SZfa#5;1$V-g^;_72b!X8S_!(Uuk{0cqBL_TdA z@Q|xd)cU4gE6FCTTL9O=7i{qERfu?-OJyipOXta5quX%94muv0Nr8#6dI+*10pZHUswI-{57x^;SWY~YLzH*8eB zX4r9iP43MrZ-pu4gblt&c=q$jboAqyA%cu5J+sa@!*Gq$T0v)>Mrfa4xWrqa%5S&x z>Jez?jeiH;vaAwtG)LBEjkgdJA->FGkAPh_T~c}`uBH-pf7(*iw5d2Lr*M9t`!E-0 z#EgQaX)RXBJC93k*B~OsaH14vvUlB=>PS%lx)^j8apRRcbE&K=PBk<=s4TPS&!ao+ zus!caQXp%kAUObOI^tH%7aXq=@rHYmNlQV*+M*AW1Q71I3mW$%Cx_yhohfQ*@5;KK z_;$SG2kSOjBjGNRH%GB1=2R( z&lcs160<8?*Jxn;>hFyaZ8XUbOAi?Wnc^kBP5{qznRGN$>=f>n5Q`mU(xlfacJqiR zlw{h#kVT&`%fxe;z*A)^g6~};tBVOFp^@IfaI~$G*li0WZj~_9G%PyA@v*;K1-3kp zK*~i}?$C`{!gwJP%AbUB#{wmZApx+K`{Z*oQIYP-9e8++)h(tryY9W5Wx*ft5k&6nxQyp|t?hUq z4`xNk_6-i8VI0P^V*QftAvAS*yL%29?vIQ3oTyx{1#~WXO+ZY?pW(0TNS#$(QHN62 z!|UH?J3s{^)a*(}0PBq8W|D~SEwk8?ajHzSmgK$Fw1|GRxl$P7yFHs+6f1faRR`v! z?G7BGUEbC!;~-Ez`6HwklICQ?s$2wNH1g``)W!s&I*TjMdE3y9Wc8x752kpF%{UF; zVM_+T*?}Pu5G(sXj5q2XRY>GlUS4YRAcL`3>n^ytBLhQ*qkBYZ!hXScUqGdLaKHI$ z4B^9o&2(lwLSt*Y1BBdu-P5hKjOP8LDjKcb^@DtgX~euB)`fZ!+EJq4AqAT83zQDt zVVIAJA3};dv2&|+Dbd(eL%#kle{`zx8-0I!5z&^!VTL`(@`-d=BajODvnrvr%3PnL zOv~+-gJb~52pQI9U*0;)S6}ZJPZOpsi6B|pd_1G`l9*l{bnbV1(N#AS)+ms~88hLJ zNE~d*BbY<@&~tu1m+F&9Js1C(7Zs4pJVkCJ89*K9oB;;KsH{CCuHRl615m~%-PVXv- z@8NVK2+LX=zwb4K)2E2qgJ#ANk2!DcG1>cCw$kfk2as&O$`gjE=IY^GxZHRW0<0&Y zv8wpB6R}h{ebM7mIj+Xe%i!=i`p~>45xD>cTqwlvc|UBBNIW^$A_ii9m2RuSJiMfV z_Yd-bg*NbhsK-Jj*LUO^hcEXa` zCGb`4#&Xn!#;yoXu(l7})<9#F`zk$R<2`r1d(Y>;)rT?bU_9PSnM3q-#&P3T zmT5ZiCQ1BdKaj-mYE91X=j(LB@kuHMt+7YLv%)JA8H%;=DFoLCUf9(~HBoEHBU$K& zzo2iUvl{y?&0A~QC$RPaaf1u%1<>I%Hei*P{7RssoOrouJepUg7_`BWu8FBdi=K8o z`-Oh3VWmP&W9CAxmc(MbcALJgi|kMna6P|yXb5rufz1c(IP-Jadq8i&Pqr~PQxY!DJDv>+a;*^r^X&(-h(Dv=y~8p(u?ZlMRQm#K zvTfcH8zHHk=^)DWtodsfs>4;fJm|hXRZN89r-Zf}DP-bAS>61qH_7KJ!pOH{wsH*o zazBf|GPxUfXALQmRb~AM<#glbYh!BT#Ldyk91}!>Ev{pyfe{@M>lwthcS~Nssm8@} zzz=**>S~i>294+$CHQ^U=eBiAl;rhgM#!zsUZ(VII9T!e=hVUkk0_QWk6p)r#o37X zr7O4)8!D6!hlDqnu|J2CD0is7GWS8xAyN4$|Zw4XZ6` z-C1Y3?myM-4b5L(cR`;5!9`ml+sKWVw?_2cO1xmijbkZYkl1EojJXl*!RFf0h)8ca5P#O_)H*J<>+CGw7nyyJa4oO<;~a(e$5(g z6!?XZ;vvOtZeD9V0+0|KO>mhGRT0cNmE5iKJ}f?B{inxlMnu>?ZtBEi;s&1jZ9T!BK1Uwvow;fPdlO_szRuQPKRZ&7e zX}j>9QLupMzvq)sU4;%?&u4;dtIbon6`xbsGURD0KM`#|^ z1YpN=!6P?|j-NEmX^!Y1dh1H)aux|Fv+e^1UhP+!&FgG3onxy*G7`@=O3cLz9oJ#QT}>GV>X= zTZVy3JY(B4J3|GG*FI5rA)wD@cr)ecj-b82_nj!a$vZgNF|j|_+v(>0jd_@PS4G$Q z@us=5bP=_S+RPV6%q-07tw{F!qLnyOzVO3a#@fB2%eZWE<_NC-HE)e7KD#MXxGg z{P^w@Wk1*J^i6HEsYMCh6%oCnMG>@&_mZO|U^`3Bi7S+@=U~cnM&Xgn&);1B-}v5R zPVNdXRoU87B$A7?vEbE?a|Jqa{c@)7G@1;nV#Y`}^o zVI=K29u|x^Z;$g?_ESg@P+A^PllZ&t*cXEI9paP&i_;pgf_tXxU8L;` zXWE!$zDc*s-%2&}NYJ7DB;hm3`=yl<%URJ=FoSK+KamtB9;&b6aibn|anid_KGGI| zh-0t-sUgdNGk!*$KWcHiR}n&1<k#EszVJ6dt7(dOX-O9UQ_8bQM>jfTp z;Qz%qynPbsLpexzXB#P{Ml`jaDf|P{FoE^Eh3~ptsi>1YRs}H$Bq|K`BK-~4|g@5LY5oG?TlSx-Oa_A^Qp+S%-CEi}#7DnVW}NO?-L5wH9d59j zl2}plJ62mqSeNwe3CR*-*VXQckYnI)cSE_ldm||l5+{}X@TE&gnWbGcYCOhie9>fo~7&iA=$Z&&1UuQwfgVR9uh212!Vw+ z72(xiBw4r_IQJB5xDk9kXrlMJqSFyL+ZnUu>}(!F`XOp;MJml>8XZmqqDxkbXgdciaZ{%g48pR#@;a+@ zt*roJ5YnHZ4BI6C87p3<@+y*V{{LHZw_zcF)&2&Spm#xyC7Gz^IuJ6*i>A{mFQdiZ zllKFpmM2_k|D49-9Q~E1$b}Rt?(}g(jQKlG$;n}%Ao7Em=avY}kFSB)kD$~!6d*OO z>3f#)#(*?Q1B+$y9x-53iJpy_hQ&{O%8?DbE7kVTU4m&-ui>Hsl!(Ya01)I6(xml{ zrFC;u=Yiurc4zh6z=6fpH45dB!gl$*oQDR|Vlah2a(tRS)48I9U7g#kxxGe5bwKl& z@j~tgMxV*CNI$#ojaD|cWO@3{JEM!xOsJ1WR-YJCVSHS8HTQqT?Vn$#YGPXQ$#RzV z6taU@1NeM416KIMiE9oqGNG#hC5fUgo*fI+U3hF}FP2oU>0!8TJ_yL<+Tb_Cnjl5) z<5YD^-nAh!qrzz44aL>VK2+eghd;hVtAj(;fd`umLL6`K+>kl$Y5&~W=(z45>E!v3Puo zI%oqwX2_zlQW>NM>0X{cV&Q1|oz{-wAT{g7vTJ6H#WZbNpMP#m_)HI;=%c8kDBYs~ z6qQJ>^Aaxs73^}rRymnE#|PXgizRkZf;>DwKS0lc=sKXu?U%H*{+^gG)!ruXG7ssr z658VRE@d7nOUyz9UF@ifaIx$cVi*vj+|3EMlZ7)oc}?9csp)5kqLPa_6mb6dG1UUC zA_=e|Ui!J!q6nX^ph|h4@j9l4)oNx-r-M*ebZmX9Ig&r}S%)4WVFH7~4+I->K)U$K z(p_#+@E`99BpWk8Q^pg~7UXE7_vT6@b>*tYW3fRqPR%g>LLd}+S zJ~85U9V4W%6pHh+uHSRLVJzK)>qc2i$BXHw3sbZQi|6e;a;4!BeDtCiM5&gbofW(V zz~k+JGl+sO(!HxMY^%!;+l$o7Qw!Q5etz)i)dL7Y$T-Vk^|p$@{Oi zI|mN{Q5OqbO@bQ|Go(ywJ*J1X+SPr&|FIH!V5cq|MRy)h>>bwvPry^ya89^C;r~6E zdJ_=W|E5x;Lh&g=7}-T}-2_pKRpCv}6wJFkDOc`5a5~S6#ua4)0{f`CpHa`fjPf9@ z39)6Y0Cq5cy#qB6h6y}vBC>krokjn*m8qjZazRRkQbdBYYU*E@1HYXcLG`)I*Pke3 zE6SdBH`lP}DIc-ko4M^}OH_ zq#(c~a!q2rY!wllfD$z{A0{9d64vk78DV@tG$F5h4CFGLX66G>I|Hyg z1F$;-usZ{=I|Hyf|MAL-nt~vOS9O!zx|L_l>t2L(!c)cLh0c5v&W0PhOl}sy000F` zdcF7P+H#0IvKV%5@IHi-T{0ole6$o;Zq9$)N*H^fRqW2y%^)*T?h! z5c7~dz9VfbwDzT%sZ@nj$quXS+Kp7NPyhi-E}cjFoHiz;^0PX%ry!Nhz(z0tK&bbGEJ={uO7782S)sa zC}-8_l^Fy|_E>HR#gFRyE;!n&F*b>4_Krp4Qi=j?efgVj9@ng?A?$x+pNxIyeHLfe zCp%ylucOe0b?|Kf1&%AYu=XsB9w`^fGz#T*TdL6YWZ4HJ6e(^^fR37Wf<)G-VQ=RM z`B98}EW{ly%G)q5pLShu)&6Zoxam*ueo~mOzFHi=S*#HI?ZJp`m+2Cz)BWb}k;jdT zbhjWqbi8~@?z!|Y6k|kg3J3h;AcqD^&NnnvBhB!Rlq(P()x}xubZgl+Qf?er(Ox3f z8~N0y7&j8MFsQUY_MSzk5kTdiIaApaeQdP}djMqh#jds8*O}9_FwqNKA&9j~AGf1zYks+u1+ZKb*4qm!Pg*U5v zLe;uTg}%A&-Ph)ANbMdPM*A8eRs+?^wu7P;J{)qh1^eNU!+MgLIc0tF19=e(*ddH_ zL?d(a;4mZ@9ELf&#L^N$>%&W)^DdoLoVKDuf}ITuHx@nDpn8?SSiLA?_%M3&|HPy= zN3`4QPloLCk`nf?a6UM&DNFQZ;B8g%Wy?J0i?Qb$DK8av_gOz|(`Q13q>Y>tV^g0P zg0|&?apD4%W^Rxa?5^kvr{{-_;;O{FL7-$qECzyGg5IQL9~|5M?*-yKmloxl>%}$S zv}sT)Qg!I(!y_={9IeZ;;gMd%H#xD=BA>?$ZK`Dx_vw*El?60AVbgg%pElzl2|DeJ!5l>p94^NyKIjNqr=RP_d5)m_* zZJTVU6bY9W_1NR0P9y1eLlWSCogG(D&OoIY3c|_~g)$^N6}BWuDI7tzkgo6_3<=p? z9T*`0{P{V!R5fV2eL{_r6J|cI88MjB8NLRup!h7~Tv#&(lAZP;L-o+q&_AWZ_o&zx z2+k6#5+|chZK7}R83OWDu=b7li7Xu{iVTNjN2@*k=JVd4p1V)&lGHdgu0+N07<@4uUX*WUgftdR@QTrG(A~l!qGubPZL;L-bIe z%#4b0M^v@5TjLN1GFK1UC+j^k1IUCx`Ha4S4q3S#k)TUm91#JV>&EN}9LD0DE0b65!L9+MY`Pc8 zb+@_^(pPQhP|X8U8xzW>LIPFGgNWiS17qhjt!mtdY3vOHMTK zXkm|D{Y0lG%zm?0FA5?FrzsT*3G%t7Sg*<4Bh;rVH~f&=FoXO{t-sO(z|1H#wt|k^ z-U))c2|N#rsq&2bUw_MUUpw;>TxM5chwo z68XK;l64T#Jk_uN56r3S71`N_7PR)3j3R5QT@f^0A+Kq6uf9T8i%cJ^Odg~1pihDc z(OdY=@Qu-T?i8Q(M{;zsf6D9bqjA*tBx#aadTYBrnwPd=v&mqP88Q5UL8F}iBgyk% z8iXOgmA~jRNi|R<-}n>=Q!LEXu`>q zyXHOmYiq_ysn_m;HN9J=z_C#fTu0HYu>^6^?~yUag8YbCk(-_e+NtvcToO;;s9V5~ zNX|_6$6h9o9W6_5s@WKXW+U)Ye_e{wi!G)Rz~Df6P()-%ay4@3!iQIQBEh7M;o)^m zg0^2(;I2Xocq(vqt!47x$-?_J7xz_mvKmZ%*BAwN@={_`8w8T7r1&Jx^7ogo=iAuU zVpZ%?!z1WXcg`k)L&;zr%y%kXz_%^cGAXfsCO4E3*hxTgcvr zARo@a=dLc@$e+=J6rU6$oCkeV(iCobmI(mA0T7n&@*I>Z>PQu|KuRmeAcA&(1I+Ht6FaFblY-> z3gM*FISk{|5_vYIqo;aUQA(+Vs*2OMvoWLcaaTe%Y}m}}u9r02%ffFk8R%7fXAp=u zX41XB`Od8UvYnt0gz0DfQc(LQ*4((@V_fcDk^pXL$@DEmc2h?nDVDWG2whV>$8@ z1Yew$i%xeb2~@wAegf%=Z#y8#nZh#2&> zge(SQvGRkGjKJ;l)rA_E-Y9|y{HP;fe5A8C?TBPoJAIY*1J0q=nP#PTh57V#2>4cX z6usC`I@k89e8+wf-mL2dGN0onB~~c!8T1^83`RGRDmR0kz@&+_(Euutr58$K-pmP3 zap2_)mkfaq`7qvKwpq*7JuuA*>XxJY^|-a)Nnb3&ZgT-yaPrV!Qj~WN3?^I}p)Pyk zK`C#;G$vgm_lrd>FVl|D8kH{0Uip9jKm^rg*LY6XI}a!$Zi;cyyfu zP=@?Zg_%RJ@d4c4Dmkb=G)guJb@x%fGp!bl=y(#G0Tq_TP@s{>mPt|?=9t5Xv;J(+BIH zHZ(DAPK5qOu)3#SGivR{nuNI8@nc&E_KpjE;TukM=XB;E-_}q;hj)p@>1*lTbVGi{ zdppdl&hX(H$N+*fs>qQ|`iH9LdF2ALx5WJCg)?o;(6j&oQCgCG4?xWJiTJCP_?Ez( zu2;+l2M{%i4{LnVKK({)a`!Hh1fR8;N4qP>NoiI7;o%m2vg5^zt-vmMW7DpMu*0rp zGPi?!T%cBy zL?Bn6bE$w|@wmNrc&9!cF6teRySv!}3onfl%&_vu?tnTulT1t);3H}T?uRtiCa8ym z9ursRsZ?{3vv1a^>3kT3((bSp8i;Nkzepfu<2~E6@)!19#qJ6G32Ob$ zrE`P14Y5`Cr?iK?qH`#`yJHv~`c~6gs0pmi8fokgLaH*yZF{ZtZp_51gzIO@V+S-; zj1D|uKeEcQmWuOU_8U0S70!gUFg(GiN_svx0yA~%Q1T^1fuHDK znh4)ddJhA{iI54@WW6k*7f^_+UU2)k==?)_oIhJzi`05i11|ODBf)I$_x)RVYYAjm zV*B0!F>e^j3^nnZc~XXZ0xRj!E3by zc8O?<@I0MiXSr&01tBvwJh&Ndes^of#rP6jW5BZfb=5s=rAV36pJ`tG`B=p4g>gPK zMN2_=v!o%Jy>Y4HKfJ3IwcIb6@0&C(gHkZO*y!<+IJDVciBbDMkG*e%o|O8C6fR*fxX z>8$hOne0Af%wDWJU$X8{G+1H(j9Mv&h`FqueUCcCjp+dd%Ve#@64jr(s18uhW3(Cpsi)SwU3cTQ*2{H|kf4KF6F|l@*6N;bWA;ssJ0;+mc~0fNV!Twj|Y6-m#$eKh%5D#AT+es z`1|Hl41eF&CFU1aqcB!59fm=yvCx3&Hen%lm&o!06CR^$UZ&IVQ}IfbLjIxfq~t&2wwB8X<*AoC~Er=kC}0JA|iY>H#hC}J^M#)R-udLAQNZ%m?7C6}G$x>jQLs2kFFXSjRPB%LYhrg<%xgReW%#^4q*8O#Hl@uZw z=vJjw+59!3z&8UBF6)8*r>NlE#kLfDiVL-W9MD>u&s(OH!h0Lkgo-8ci6IbA*)?DY znMx4p)rl1Qr^5~0K?S2kW3D8o{Xbf{^biDK@7 zI;xg2#S4!g)5@hw)#7WDijN(~I=}908OuDjt|bU`5cZ2^r@E{MS!XRd_s-&wIOO8n z14`uI>BHm$OZhTnZZQvv8*2+XpNMeWt~J9A9*X0X$MHzCtqrBmoX4FZ2>e{iyI?X0 zIB3H;4lL>ONP=T5of1cHQnyDvDlssWf2o3?(}@o=O+Q2z_E;mcC?23cVvbCZWfNIP zQT9aP-r7a}_Z*PsU8$*S3|(PIFvSChIp%b{AaMYL()JjGi;yFjt(CXm!2 z1Oc$Dj$~wZESRpr^>$i99Te;VEmUf?)E(vzm5g~tGbm@Dr+Q9tUqei47}zb;QUu<} zKOQyBP%nCBIqDi7^aLdA%E;*vL`DD=SV;Ro zJm7ioM5m;$Nyj<=V`u!IS=R+Bl75E=!Gm<^P$jbsc1!49)Fxv0n+3^Ad~DUmgElcf zsQ5-XBSl4(HSK(9wv?nb>Ov;#TY7#$<*RCCo$cXv3qLn>Ry#RY_Tn7D^=k!nP)sFC zuecXTST`Q$-Yk4xwFUg+$^S+t-ip@W>pNzVHK7Kf%xUU<%4M1ZTu)?4S~xGT$w>@l z(Lu25O1Hyq(oiJe002dZLYS;)oKUZAcK>2QC-aETgX)v#;Crtlk4V2#Jzv}qvd0nd z4{-At^;Zrhwr9=1P2jEFEsGPIJjr^WRMvzC-RyngF30TCiK3M-jLdj{)UZ?MbD`a| zRh^tm#xC^aWG;|N6V7afF{Hl*m;uap((b#rJjC{_bo6=mWz>12vw0^MGdla_N}YOU zqXLIQWpWE&a(#qe1~4j8aCk~>ecsqjgVn4Urwr5)x((IDKJ3=a>Aok|wM5d%80z^gF{lFN*gGJDtdAY5~O zVZQ(=M!dRS#%a4<2u`>=g~Q1;fqXFS=s0jZrctjcovHQ;cR%cnTHy71!Q)2e#w#)d zomPhpe)qt?#GKqm2V5Qz(M@7UfuB6E&3TEG_Ip#4%}Tm8*CGwpYeO~J^}!7U9aBV6 zuW9xxM}+VSsPP9l94}K_;$h1_qum5(i3Hs2!dU+IX_jtQSxNhqdCyOjn&TI>{UHU~wuvz>*un5Y8tJs3n+YlkjyZ|g65_^yGCxM;DOj(X ztG}B5wWC1h><`uZ_MVYlo)~^II|a871t8)$utU~0c1cpms4n07Ja=S?7kNLp!{%7HjX@V>i`xrMQ*2_yyhK@*lpUt z?3O>JkLm^PddkCc1qPedZIm+x+Y3Q}yg^i8OB$yu-nF-Q*`DDngB0lyX5JEUcuYh* zfq#XR4Ku3wu=>?@s_PdQV*xji@ZOgVg0wvKB3!lX&p6`z7?vHCRPm9pF?18p9dAc7 zv>4e_H6g@5M@9Wy2*L8=ktpKH&clLnWb`g#*UK$vmw+PR(v*q7ey@2wH$6eK*CaYC zM9IzWBhp$pO0Kf~j)sru0t9ohHlRzpLJCZSpo=7{ov`?vu&gx3JU(fZ-*7Mtvs^&& zO7zXfhtPNOlp95r--_hd&qrb#j%6~SDDeunKS}#GrN=y&m6NM8FQ{f%<2KhsVR91u zJH%opo6z>d?roSiH3@%VHV?IFEY8SKjYd^ExF*FpAeVQ_%j$?WNIMm$+T++u3O9eW z?2S1)PMn2IA0W%i_fFg|-swWgaF;cIum;1L&Uyvlf^dAm)oDWZpIeya$@l^ta)|?# zejPOw#mivf>3|=20$J@T)y&`yZI2Yid-w^v2eg*Tj_ywVVXaq{GMpO&y%~X-D~c2_ z7t2U8)@8jCzdCYSa~HO!P0s&OoAaPjT0gwVN6uRN0ZWp*&uQ|9T7rvgrZ}Hd(`px6 z7mZ0y5?>SZG9xceR!h%iv^dF18E=|kIwR-Z@y=!Zit0UedoZJ zGg3~v+8hT%&)Qt^N}Dwl#hgNG4s<+y;_eO%!cH;-JtrF}`glVh3Z4tJQo?%=7BY8j9V7ET!I3{AGeavMHh=v%FZPs z^z^jlJX+dkqvRr=QiN2Gd%C;c*!a!x!jDf`u0#L;=^FZeUMZWZqS>rZ4im0Yu3wTn zU(d87smcL$>LqD1^lPqRT%GF+Ey>9^I9VGfS^(2CZ0O6K%D1Qz_5L~wPEPkR*!bs2 zRp=idLy~MfthuZLlOq8C)M|8{b!{9ocp)H`9rG!p{HxAs7G3^m&P?jhwV%c1 zbdeDrHLR98SNVIIfG>r!oG5xoHUK8XX0*EmqY)~lo(o+yxB_9vkfg7}rSQl@rB!vp zNdxcgaU4^Zb~*GOw(us9AeOCPq%l~r#}fIx@yy&Rn1Gs~n0>a?TRt7!lm%=K)wk7^ z0E!OH9J=HOH+vGF?hcY=CRbvWsLkMh8h}2bl@!2w@1|t~uyCs^hV-`jO2pI!7mEGA@iR0AF}Y60fBXVLyfYVKglDJXw5a^Zhfr^sV85OE6j_o|jP;Q!V`eYsrr zF{~jpi>ex;cFRE=!g^8y!WG6Fi~@Y>0lt@dDD90t@#R{4VRp;lBbEu)4|TworSE6b zz^(o4cn;5Qc(Xs`l)RfSfh2}q{cRZPDWuP_d7Hm-eo!U?!Q{Qos_8MxbS&s6dF4+! z(Cw(iV!CP$n?FX_%DSG<5eU%Jmm3L{%(?Hb=ZPA8oVe89t4;DETt$2J^?dWU?0tNV z|K_onzE~E5qL~;Vp6^NKajPH!&Sa@`hc!5fD6c;*9psHURy^Ck2xzq79H8*$KP2lo zdAM*fNV~rPELHc2{0=`2<8RzonrGE&rogY=%fd`roS$Q3oPR_&Toe&8lLn_X1xYVG zw8$gXX7UWYg%`ddK8#^0CJ54hY2K9$gH%`#)+qm-wA-vCx|?I)47wMoejq8mTm#5h zrB5a+M*R$PbgYv)M`mTP)%1}PWUeH*N8oD#z<1ywmxTil2y!4W8vA3i^SvYH zP5ADgIrs0wBpITuh^wB)D7H-ibz>}6XRVjRwD|F^?+>!r>Yj2}4VZSxy!S&M|15K=g`?e#asn|BfI zXs-fgxa z{uMNf@t;cCk>y{HS&O~6{(MQJ-QlD8V6#8sm(;B4H6g-YXYSjy(eS0K_mV6Wf~+;c zg&eW{lu9t(JF=#GGq-q|NMzd;8zL4}pBjJj0PERP!6g6?lttgxw8o}lSApLl0QSRx zlMqPVyE{HTla|jBC!w->56r7(9?8x9Opx=lExz34!uJGF-g&;|h)sM>t`>~s-^o*k z#WHAovLHCm^$q`?j9kK6Qh26xMx{gKS6z`;)B*fH{Hzx1rvz7`h4KORhS=kvu{{CJ8vMNrsc zg*fi*IC;`A@P5xI9sq`P{xjYrct=Pg_&Hgj`aR2U9lfGCPUZuu(;}Y7;`p~C0Ygn~ za6RzD=&HXkJzp*R*wI77)b`n+j@ZhW2x;E?&7o#L5*}F!M$Ga(_=zXlrdGT*U5w8P z0tne8CAbv)4efOA;rS9hCFg&{)ym#9ky&MOFR%4325xj zwY1|V<~1myPcFho<7TC~G2`g|jblF8i0ZV%Rj9A_J7q;0=QK&(mVU_7Q4WK1FdXIa zRKvn$>XSQ&A3~6bV%kOI0I%b1yFA_=B|Re5RXyO=wgiqqP;QS!!b5vefgqN{T}~@# z%VtnB(RBoW)(C%QM8>Bd7>V;wZ8es5M59z4k~8bUJoeu!qzk0r(%6w6AhVYKw&Vd? znnOY|vkF^7Nu2@d64ws(zdiKTe>l}hMyAc8-EN-}XJ00}ZByz|M<0xIYE{(#S}Vql zTr3fLmq$ve%MzcP?lRNG0Jl`?V3vAiEHB2OMONR#Y}46f$>NhqT-|ZFlcCLJHJY4l zD|xo9BLCb38;ZRlHVejYhoZh_hPbse=bErq7z1XpKDR*=(#J@~WkK}VpTbP&k0T4$ zn&J2k&1Xu(H5J3`t2#rfCVHJ#r>n-2JdB>#aVTLXd(#q(dDTNDFXI&uAL8a(fFUox zlYlX_2JL-O4uMvFHLB#3xvWd}kgye34WLBV0v*tF)T*s=!+>rZ<9zz5D5?o{4jTK7D8U`tp zjXnGxgdcs3rN>!o2el)s!c84$T*(?lB#?N)5{>FntGQ!n-@#Wvp|`<(mRa8s3(8JI za3BBx7-oLn#yq3D@jPrUJe*mh)y^z-v7X?Q564pT_iU&fWy+#52s#ztdlckOIW^gr z0cJsA8z~ioMcVK`CJX=zRCZ}{jOAfHZ}s6Q*WjU`$HD)Pmbm-cEcon3C_mVGxa`5^ zvKV?AMfpAA?6!fML9b(I2AM#oG%46;m&#Q}?O;SL92-mG4l3J}T)eFJa5OwXv%MPR zUhiS;rt@TyS^?J%62BVQ@XKp*((Mydy-b*fQ-9*XE)PFE1mB?gQ@#hxO*xAh1NiK< z5V2k`pUKs{O>_;N2o^hV{};~t{?9gIz`em3Zq%RS>v_udw|B0bvbZ^%G(|umysE%M zKe5Q*0DEUkbk(d^k;0AJy>NFvON3=J${F`0tpckkVRsCB{P8_UQL;W|w{(gAdn%(- zS5Dnr(rwJgyPb_3der?q4!L5$GzbEOhUA;OOB+@m5Z0hBvM;MJCK7?GaseIIt(9F9 zvVN35ch!uT+|8R=M=He2T#{p$Uj*gWsce#D18Ke!Xfh^$gVKmwkjmNn}X^Qo8M7j5Iok zE^Iq-i_(78bAZzz7kj$xYTsTiomZ_?A?0CujTg7?S~4V8F}@&Kn;evgk$fK}| zmaR#stj}Z_Pml^tO(XlpvshNt|VKZvP$}eMZ0}*HvhRBjJ`Mm*Jq4 zYcHm3pu~Y|uLhh03@IXMz|G@}AW?{P=a`+NA@?xu$aij!inT_z!Y z{TO{7Ug9d20!j2--v>&P@YK^mMvOFw!DxnnDH)363=#Bz(-U)ghZv>DD;TIAM~H96 z>y4q;LX?xs7Sh-hh6LNJaRNv&7(29IJ$u~I;^N`Tbrg!uHGq>>Ov}&-XxcJWFYYzt z+{M@*8h#Y_5y&tZ=Z=w!gERbLe_cepBy0JVv7%Js>`1nY9dHJH^4E2S$I`TLMaDD^ zyaBS8KvY+Vs)eujA$_N>@=z)4^BeE}H-}PwUcgeUxF8ww95|*N86LBzZ|W3xGdotA zyQGDt5>$Jx6a|m6v^0}EWl7pI-_WO<`*Br_bdRa~@>6m9O@ zg5JZ20&>NV*+jC`b=CXtTYt_wvIV*~&|KH4ar^%vsv9-+xJ)u|9F)Eud`(ERIIqZ!ah@?Ffre&1)ES)Fyln`CSb;%P==Xqx(A!Njp2%47*F zL*TA?#uMTW#U2vH;uXp}3fW0p3j02@ri@Dpduqw`w0hK84=`~`u-#6d5^zh$(;sl; zCKXOBjsW#YX2nw(#DsY4DTQ^vIXh10Hco4MQ#bv$h*p8dyr4zixI{;e$rhs}AIS2Wri(VlN! zP-a`x=|^BVY+m%z1U|t!+xa5)7H47+grlk7zmqS?tOs?Mjt&2JNP8NXTA|~@M;0NK zRvd29NhVHs|HzH;k!zfgSwxi$7+gwa3O~A$$J6=PmI8^~66>^oQhAJ3#wj0}!3%Yy zcM~&p)WdAkD1E5ZB}g*5(nUDmK$Vt~`aA<50Kn@x_Hig z#=9aHx!HmRSq`MXN(1unsDY9ByhgYE&+t*M09VeY?a{(1vo;;uevE?(t1?CABy^a| zhKvSoAQRS*&sSf2=~kh|P}Pg`3$}NPE9jk#uLMv(ksjs^YmT{Nd_z%)nD!rM$}nF3 zFoT>jF=hjQQU*V>@2N3pO}?Etc*5hQ@BK$t=Uwk}^Y75jLY~&%#*KuOhz95q_X0O1 z0HJ&{@z9YTvd)!(`My5z>1l?dSo4#yzRggtyJi8KKgbwUc2($um;fm%enFiIQp>WG ztDE2c7$`6=cXL7M0sOWuZS#Xbs-&27FG7>SGB#>zW_biit+(VQo|yCzml<@aaK#@F zVKRQPQ4)1O3EuJH6p8-GB73({|IPNG77-SZ`)Y)K_hIo#H4!MG+a=rGjFs=Ztk^iv zWu=>AIJ-C5iO<|Q3HXiAP~`Mr{Im?Jq_yzniE0zx4JGb_9b4Ibw(V_FBZqn^vZfb( z4koQwj?8>ed^dbg|QL^8b6*}Jvqa?Usg#jSGj4ph^XM%Y&<&$&5IFV=|cf{)eQ?S)O z{Nn?U)D({NR!q?w<^)jAc%_U;6Go@oSqNa8&!2X9zj>2ZG!*!nEN+W1VNU?au0ebc zJwv5%6KJOhRf-<*0wYorbaJfB=q~?j@?drCHJVFyXkOl2zH>5Gh)C<#1aCN3K*E(d zrG^}U+iu(u$(NB@^6X)y6#Zs~S~TFXN1wQ3lnu$y>onzz z`G&MN#?xA}S^LG0zhen;AzX#B-j=t+Ajk!Hrp5cRg?pX$ebz65;@AF))0*{ z0WS2o#Af8B0XCkklym3-Mo~3N9qxyxcx$iz>)wR%$nv4N+yDRrSd`8O*ccjiw(<~& z2oBp@ZpuG57NAjb-}9mMD+k%f_D7aB>S|Vz1mwADwgX~GfomcHxy0THYP0hR;*YfL z3`YG&FB4(Buh>$JFSX2107mjQH zg1k7*MWb*|vVmUG(Z?CBSUIGJcJi_W-9da%VpA^{eAOAc(IbQy?6xDD7=d&H8;<8_ z&aL^DwbNAgU}?Zhc)&!FcwtFi5%SLM@#;VG>s?jjqCLuFV_~Bys=O}Kx^${IOPxbl z9^C=+gH!iObZyBIBW9Y7w6y6;rtpurG(@FiaYVKWNYneM%&H}{#sdgzc^(&JdPKz&0nTu-p0LjGUK#$**5!XXG) zj=VxMq%_kq=KUFLrbty>1V;)gjclg}9)#xiS$$chOe5rjR!&|fR`2S`T@1D%gi9E8 z&38G&YDOE9LG~WZK#9wO`{UxEIy+OT7>ARUx}I(J_cu1Br?fdnI4bHI`jb?bB5fY?UfUwvdqEam(vMD|%Wo=M zl|uA<@NB>WQFU`kw)IDGs4#&&ExD6uNxVbyB&vJi!ep`2bxO7TTF!D2tshoua2YXM zhblOncF%BC4^W&ybM|k`C^Vk_8IMO&KEX8j2#c+`D7dwn(O=ZxFjel~v;{qDwIQNv zw$Our>*`gYNqj-bqZqwUS3C69a-Qm(eKlFv-gE*+U*O31AdZ$QYCwcdoIUCmQ78yY z({!)ocShoQGsdG4c=-D;RnnkE>5B`h@Tl@e)NFjB?(zAjx5eZ~0jR^l=Z)>Tk-3x! zYFZD;+|)biB`iKle+-0S>zKrm5(ZphNOOHDxiq^5pMO2eO;N_Ejb+ntoecGyTH}en zV1Jgw)jieW&Ypa?BY)xZsP9cc!+nc#Q$B{KVn`T(ruaM=2n~YxIa&w>D~VwhLFerz5ny43B&LM^=ufAYG z&nCBAgFLTU^hFSEmCOeM?*wWPP$i1G>YE*w+|X}uPso-+UAseN4&g^LWTedONm;Ke zR=7McV?bXM18KlsZOEH~@|jKE{F$=HUWzzJaOVy>kv|CZQ*1@<+xN~$$1SHdgG(dU zcMYSzXgnr7Z!-&d8IwR%oBe2z1{nc#9PU3aE63%{6wCz^Qmqo|gH+F`T$9QXQ&~2S zP%&ui{fHQzJmoZwzQ5J7ep){ILIq2dH|QQvQUwdd2=^G9JR3ZH)V;&F_7~@1+8MJ| zxm#x|Q(u&16?{*}?73f+^79Y7JIh}sOPHEqb8p(GVq8pd3ewF1u37bi_v+Rxyfl&t zLIP;39SbSj+~C1lu%^SSPHAqqk-UsoUiSdEU%+~nP`0tbQw>ax{G?X%Xw}H?QxJ;i zhWJ$yNyLtKzaCO4{}oY=qwykyXj@mEjJDM!9xxef2^P9y8YRm}j1NO>3lM+nUuO93 z+LF|M!f=7#Tkjo@Rd0NU0xa|aT3zdB49L3<+f?M_dd^ADPOU0+V96j2x4qg9tQGT= z+;0h8x!z)fOEX}rQ%qM?+giiI`w`!D_Fi>SWGQDjco6*IGF1BTN;dr4&z-6$=sD( z-nL4f0++>}4=Ic0pclp`BTUWnG8|j918FHI_aOzO1niO$Q*+javYFj`i(IiXP z(rfJLr8#hPigU)u)k+2qexSL*nF&T>Y@bVkmakroE^xfpEMJ$$GCSajCWUPQn%v=H z$OY4LV_~c9K_J{<3JJ?fXggBJPV{^&^U2>@vT}exwA?Sq_$xr1b|pu_dCz5kk*9P2 zlR?ndma>mPccV6u@TDpKjqMD-zuiz#f-XsIJPQX*R>o_5 zeyKUP+ddg-mZh(+&q@0#S%3_MJb1$Ll$m+VE};+k()kjv{r?b@<_k5KvNiDh6HMOH za=X3L2}x*<87$>PN&Ylv6zy2##cx9rZXzcYTvB^dmR4%ruHjY|mI&-7qB4|5mNc$$ zOfa!Z1#mSz^^IOZ=zDMUJB98J`ExuwDfw_d=8Y$ictk^s;I(ZSU<;@$r52f3H{s3& zYm1x!}xmZ2sPv%MsZrF zX@sY>EfNBDG3vQWyD!uPl$8On>Sa?|uMx5~*QPlak<>zU%3kyU5XyJ*d#5xlea|Ju zasGJ-+1Zu=H-#!bXyc6$^3<{>4qi)+r0_OBx!&Ulw0k1uDjrw(7Ta~UFr!@`w{=b9 z1DLdG(+ege>;mY|o{%C@>QMn+?;#Wb5D*;ZCLl$KeG}vOghlqqE|J-14>y!~=HZ80yxV#4FoIu6L%uG$DA@3j@{@lFgYkKebb4++ z^ZjPCOEgohkYEHjC{Ig)Dbg$5j64^044N04&Ol3W1BtP;I>z1D=DqIuu?TCCIFQA( zq}0bX?Mov%sCJ>#Zi_JVn#na*Zsnm4ZQ&A#i(srt>{Y}7`NLPsBxi;51d7s-ohen! zT^mKt<$*kx<=phtNYe(LcNN zci@aNBW?QIw+NNy2mOQ`2aT4CeUJNjV&yCxJGS0kcX^PCnYg8Ee=%qr8d`Nl6xPk3 z_anc$FcaQ{EH!Ut4rE1eF=!RTb{Uf4Y#Y*2h4>_fk&U}lF!te$ z5!tyI5xeiv7cVGim+F!X5Pvt$b*(Kk+mOzrWUHlnWXq8%b$4PNmGS(<`kh-GyZ!sN zcuelc9rL1$;i=!lsHr#XJc{0!6COaXe$}o}3kKOZN0^qcsXy+q`H;)Jr0o;7WAOS$ zOxDj4FHi_2W;}Q{@Q#^Jsy^z@DT|O#!vSI7ihpxU%Mz%b`#w#0CMNLZR=5mgUg`{m zZ#F|yxl!X(##a#nkiMhI-y|bz=ZPobD{1)v)h{Q8+x98dssOAl-UFD$oeL$KjbIzR zfKsj5?We#3&#w47rb9Xh%@1GFqa73(eBb9^)o6?TJMSe<&bi)b5g^9vIE=){V%}}; z3^M}($9p$4(55|tjhc(7BCY%O-I#NFR=dT*{i72l8+qq`0E;J-K@g8l7kYYoj>{2h z=4Hc}980uA(cjL)*Lw2p0d$+PlV>gzEdg5v)@sAyNQ{JAVF);2R|1wUF46VOaNn90 zXl`BiBU05P)(AFtcNXksTVOnFhyF#-_~2i%Kk`xZhvG^(((BFWF0pLV{8ci9)|l85%i;V%ulIb&#`ZA14Ul%aWI7gspIk9Zbm})&>Zr! zNZ#kC;WxqDbgA%rB|)zZ#1g@P?<-~=go-5>YF^9ya72HfXbLyD>tv_cCuFre-*ux$ zGANfj(83}Trg?lq6!XK?Z~mc(^JXHkomeZqP*ZK*EuNi$ z1ez%NYWS9c42;RsrZm{_t8Lj>Lw)((Ea~NoBC8gWii3#!))9dwU}&Y*CO3E+AyCm5 z$X&5U`1L$|jy(2ShIP>wiF5)RlGLcP(r!LW@N#GhU8jZMw?iU zkuPxx-HT6gOD^Y7n9xcwrXxrv3W9J5PM-7 zB0{2KKCr#cIGp>LQkj-Wj{QQxE>)8;9i6)-o1KI2D5C|%<8#$Od1RSlJ?DsVkBHR4d zoeh^DcO3uA7omp*J&Vv*vh@hrK!hOh>O-g07kT-BYQ03rEg|>-hkm17VWO47>oh_# z#l2={=~V9zT>Tj1q^*7n`j-r}K8T~~u3m#7pz7O>fZUa$|AZCZ2)1eo=ZPYU2>Szi z45yXK>*rQIJWj~hl(A2@d-d~1u85hRh4u@?yi=f1%@!t7; zz3R1rg8Tr^-MNhYIeVeYn5R8k432(h!8yVbQ6THGs`ecqYmdBuH(2E!5O|MvmMHlw`eZd()DFZXue`pD2aP}t1Bl&s zh}ijrrhBN`Uyhk^!JjcyxfZp&!IpQjj5 z+?yoedXx|aPB0zKv6zcIz|7*s_achOn|N=EB~j7k#q8tpSyNZ#gLKH2v#_7{j^N*| zucTsA8AHa~q{l5Q7#TS_-2bv^MSCWQ+ri?m$Mehdx?Hk0FZ8n|dl;}m%DFu*(L?g= zOfNa^F6~O*I`>zsu}0j7J1af-FW)8)l~&aWC-s4Ccv+T$s%vHMfF|q@7ai}_ND7P;ysh$0oU2Df!L70n zH4AG{9$z1Hsv<+95hw=CRkY3$pC=);>5C8UK*Rv*ZzCyzUrAKQAx4s<5 zZ$;cVEZS)>Bj(VkGj~JisC2KmLzbw%#RTyI^$XTDJ7S!Crj}Z%+C>q*0taQ6b!r9pBeIvaSY6wvCp+;U}a`bI3sx zLjm{re3!oD&U)*hL3+a>Mh|B`l?kVVqvtjpTSSlypnL$tuG}wGv{0$Gj!gnyhagTI zHEKoA*RWzHjTsnWs#zoS!;BopU{C!Lv=*h*AH2=A^>WBX`dI}IphhoV2L+F#mU@~3 zT3E*AO7k}zmSkbm`0RDQpBdWfhFvJi>)ChXNN}Fz*}eSXKOj>v3M%50U*o{aVy0nY z#@>u>ODLJscS;~H^gvd)?)CumcP*;^GO}tHC~L6{M3)A{uy-{m;twJ(yndSP^A~Xc~+83FZV%IIn%OX@`L@pt=H#nILV^*0hvEN497t1 zNId^5W~BoMNYYIfgO$CEWHud2U^RD{viJ3MCxoY9)#Y5xLbU|vUcl9A=6|pkKcGng z95e2#j#r-t&!;-n$Q`rYMy~rkaSaH`m4P8hoi{P!&pU5DWS7*GB|G^@%sb)U;0a)l zCv|llIj3`+tk}s?0St(-O0q9h2YC)CjOp&p@ks`Z=i>!^tt}8 z-Na15InP+7H~k2>y1nO1xt=~|7u)F>i-?lD0<*3QOAoV%eY454$#8W6-Muw@%MH?bH-#2*(rl~5nf624QfWKSbAu^R5)6*Zjm z!i^Fj3vGX#EQSKRb1^IKTAZx=T562sF@nsSePFV6n44MAM_ zXibbw+53+CwwEX~_KPy4M0D>G&A4VXAi*d`H^$Z!@{N`P>gxOhysbTfh+9vhaZm36 z0U@s@+)wBxpmzLf0f1{S%Fr}LWY^UzL4z8|!^~B#$(}rf_AIW3`NT z(S4F8A7}#*^|WhTgQvoiPXR=CnK1uy+JfXgDf$A^9HT58(ec`mGkjlgRfyKI^bs+R zMYdZb_fDPsjZJxunv~V<_+HpJPxR2uYO|e5r;uY*zjwH2q*fFp960E+_y=hucC3X= z=g?HHJ}UM5D3VRT2|!T3|HaJS&INbaR$c}<`R|0zK=}$>{=r)QqW_nw?)#?j&WYoC z#=o?^F=7qnA2R^9ryygVaa#D=4xHgDqae4j2=zN%-Du%oMFVsW6m6L1(3%&t+s`bl zX_Y)F002$Wqv(kIaa zZ%~mEfJ~Pei**itfarB!k~fPv>2!=Nu#AGSGw9Ssxec)`CHzH_OnR5W9ySIxDEO}N z0S9DomC*bJU1LC@7+X2%0bt!AT#evVRW6RvoBk zln$=62sFL~s9{sZX>v1!@Q+hk94XB4F`y)%7U&ihP~V^WcRY>I*T1;6h%WgWxUunS zh#swfGO!%tCpRSZPuqa5d?Nieg9^s-LNNeLmEnGkX;_^DAY{Uc`@R^>Ry9RjnIiGi z!jOA}@u!nPOkj72oD3P!U@+gn<__!4*7Hqc;i@4Ca5p*e2lFy04Smx3j^{aM>vfy zMY%VW@)d)9H3qZ6oPk@d_frGy#CDmY4=3}6$(y?3F~~}vPWZ-RX+uH~0Y%uJ3Kp#BJGuT z6G&tIIzgKk$|mC*>_6?V^*HH;tOHbApEMptMHUOOaWG$tG!-S7fmWRT(#(-q7qa9a z4h09Zr+V`mc-g~AjKGH!+Aw1C%2qhNk`+86feemtQcB7G+@kyXsv?}tgphoOA}Lcj zjNGkhtwXMGg1@-TwjwvPZma}MdJf+z*r0Ac4d=SpOR4w!CdD1W@5Q* z0`SzL`>tv_>9zw?dUM9Ta#?M#j#GKFnR~JkvqoqCa3gw>9e*4cvMeN#MVt!N$b$16 zGZ75@drs<5;R)X8L|w4>R6`}|#-?}lt99~(7}5zNO7KFpHD2w*8FC{>zoet6@ig#$ z+A5Z-uzoaLIFXv|!*Tq5;aX~W*XWC$pbh&d^JW8JB+CidFVH;to6})bAV$ddxg*7$ zwrQ6lFfSgM^I$%TUmv-VfF_o1nni1U-VS8idL~-qWlFnP0_R>aOD~;6(oQtU1vKjB z3UzY8C$o|qs)(P9_L_9W*1>k2CMzT-lEb`X%!s3PPbn_CSl?=GtV}%tkycO8(47$2 zI)aD;>qFZ8(sR9aD8EH=qd(R?C5Ef@)sDc`S!$bQ?1$JIITwDaZ>acnOPY=j9Z!PQ z7$PWfNLbmaB>S&oL}9!Wk=G94|DJDHqq{OMTkm+QnQeTgp>ivBaT=kE=2(BK;8l`7 z2mgJ>a%>!LkT~`6`1QR4V>p386VfmU(MwqYZbAK%BTm*Hy<#R6x^dWMCJt6V%l`g| zVnLp24Aqelz!!tXS0j(@VU-w1bv!-19}g{Ew(acXQi@Oe7$U0;u1&9Gp9G*SiCwv5 z!i|CFl316{b!yQT%)#0K&5t-po165b<=U!d0mCZ|NWf5b^{!65qk+!0W!m>+P4L{e zw`K?WydJ?Oj)e+$DLgO{95gW+?4U3QRSeZ_DC5?;t+~*{sILigG@^F?H>-!KV#SNE z^%{HApm?Q}dV*m};(c=PO&A<35i$FCuse`^q2Fc%^5~Yn)g0Fsv|6{;^8soI#r@p! z&s-J${;84*uz6`tLr~iqdW0id8lhG8c}EvYLM2>!6>ywoq+NuBu#{l8@==LS-gYB) znF;d+y8%KXHACe30?kob;)KUqN3;bq@;cS4B#oX^@LdNT7d2B_dd|(R1I0V7bE**E zkI8p~T!>H34zv8@&~F^12&VDMP{_N#Bw ze+vx|6)j%^s=d00q4?9niE4PGCDJNuE7^L4Y#>GGXJt9!U-x*aU~@^#hwFX!T=gr_ z_uN@;9ds*6G`*)@U;~(NQevRm)JLJpqr}7`eG>(uhg?1mlMIY7)m&e=6*qT!h36+x zg6>QDlp?-z<92&fuFX2_0BZE&ZBXzyYN^MwNdB@&O(sw+-L!x(8}*Ii71t?rf13A*_fhBUo({CHuJzURvm$> zuXhoBN%5F{t{DyUD~xpAJ?NDf@y3FWM*!T39y=e=bPrYg^RL5HGXnCGpIR;Mq*Tbe zOJ#(=8E`2(zL-zmv&=p8#8sZG24A6D$Iiiy`*wPX*VU+4mhC@}RV_@Zn+@gq=r&dM zXV%(M|#^=xe^BXB zbnZ8#P90h9x^{{)=o6^2_d>FGdIne4C!O+J&P1jku?isH`%FqDe56OvZDzA7N;F->~MI(ap=2eF^z!>}4oB zc}^9_OxBGlxVUgwZG;zM$7;s>_tDqogFn6JGArDL(HjV%OLNf^hnm4pVIg!q7hxBD z;}BJ$KMmM@2%RfPLwP~xpJma*Oqon^a)dncN%MFFWm1roeqHlz&;7X`+rbZxyRO@6v5C}~T=7J*HrI`e@tTZKxG6NSR*`>v2nP@TXQ*xCH+BVuf&j=|)&_3_TyL-Epl zICHQ;WXjyVAmL(zl$$7DEjdzpv&6d8g~~pSzxso!^Ejt^(l!s#ZLX?9Wu4@yCqPIq zQXWM~9+N?Aw(+mhW+pydWU{G1K-9k_aDh@gvS0%pTEDNq&cE_@s!#8?17EsX)> zdF|;ar}u_+!Dd8CknUx3ABM9XYr6i$L)fV+TcGsxIh_mHqSS>ZN{Q1tMLEsvTkrwP znKzLR_KzLO5tmD8wOwG#(#pvPu(?>{Ux$o0bn`dnolkS&nj@KrHws|-Z7r`r9+}Le zKsYq6iR#8rWMSLStid5<16alT=t~4CGWAsBX6Ab2FBYrUER_~S2tSkEO;a^vOR5}} z4u-mtx0w#w+2u_nn{)vOV2Q~EZDL1dm0OCw)Zc373vqCrdjbZ9x7e-ptdn6n1x>3i5 z0aI6pv(yI1IycS$O$#(TB`0wKxglL78J;UG+AY9Sx-x<_LtNE-uYCb;SGe!Ba^3b7DyU0)b7@tftA;P>tiIH80wd zkk)lD`Jp^@J92wfX3kmyVHfMI)#|RUe|yDMT2e5;gy_8EJH)_9&S^U@s9lyr&a&uT z2`DjYr3AFb<~pXxo`$V~p^{>}=G9W7s#SdCUs5eo*!yA@7WC0z8z>8YHoq`WT}c6J zwkL=QJOmTLi#Sn?R6_2_5oLH7sl*960ve=t;8`Ic8B#$d{vN&2f-Nhn`E#cTb91+0 z8=CBw%dp1OGJ+al)M*d5)it$FhLlErD$&6`VceM!zIjPOXc9zAMeUV+f7N_;H6d2Q zD_;^;;twhRUFz!#0}GRNNy{%x0jO0}|I6z{p>V|U#pcz(9BX}oGh2#!B|H0Ad5QoiD;Sndni97rIrj(ymQ@t4rLlovq}Nol5YR%S2x z9sUG0l;b@^MV8{~3X`jAl~^IA^$|^@{j~WY@@nBif;+n@i+KEc3WuKeZWEm^(bhhz zDn^_1wOsfKX+TjoBtULLFWu~@jk|ol+8Z$dK0okTGx457uh2%gBfg}wpmvi(&QU#= zQ{H4rhZtA1_fKInH~!>&__IfMxOKt7oLr#0@fvxiPfBX+#*nj~7zBY5RNN*%FGJ#< zu#rdUfxB{A^J;J!<@{vrM+Nv~!%0&n)m17Q?LiAB7j3E^I^NY#b*`f}M^6tYZYv|T zp_{DCSLvGG8I$mLU{s{x6wi-|0f6D^dBT3_mIz10znwuA)bfzA+#bCjt; zEm)@>FRBup28vU}8{nzn=;G;RrRmnOFP49@=&j*(#2< z5b&mPO;mSok#o1>1(NG$nV-j*L*PCDlA1;j1%Ah9|93w8Iz_DV4-pgX~* z%z+bm1|x#i@Qoabf1`-eR05so`38E^(yUNfvgEA$p`hd>^cK>|BP=jyhXddy7IcU9A z6O5~27C8)&6cI;WjzaWH0#v2k7K)?6c>!fU+2b326=zPg^BbNy6UHt<^JmIM#%(hWso5;(PPLZ1YN5)gh(NWtqHt>~YVa}S(VCwiE6-bTRtHsf*{ zcmr&D&nro@miH@lVSk4P(HGlHh2)8VyrtvWY0&7IiG+xE^xEY+M8u zSmiuA3srsmfkF5FwqfBXb)zo~u6wp@XQ%pDsskC6XQM@bWS8p5A!QNAj;QZbg9^!i z1w%h{8un@0x{usg^QntqC<_XI_v_ddmbc4M%8rnBw5(QcOwX-1^ z^~e*(V4H@u;sU#^Q$*(r+fIE!y8-51u+c2(%eb`VqMbd#_Qfg}WDaKkASq_29|A-q z@b#jfS?-hwj=MqH@@g;a>T%J*jlWl-Yun4o6yz7LrEwXo4$}N7F0Xl}q`a%Co!X>g zFyQr~QQ(cLuacG)Tn5x@8y$ibmzgC%=YaNInI#f@#gEE@rb0TGoCuh7OBasknib|U zCptjwRP>!AS5V^J5VD}1_IT4x(gOWrxFq;m!Q~%pKs8Xx?d9mN89ftNi+Hxpnzc+HZ}Z0yR`1Vq!PG;ad~;(Qc=;xFlYU`;pv47bMeZ{>B~}J82+y*$6;B2{|r{bDgq5 z%Ph8AUGX~@^Kejjh|ER~!hzsntNChRabVrJGtP^bZfY#5_)C8*{!TIDRgx*gwsdOT zI$A~>%!NT0r8RM3ykHbDVBr%dcuWmZ?x5f)F`c?~v7bo-g9aLFKjhV5rzHV3TZ?xn z?~&z7VeC4va*IXEhxe1nDe~JpVFONpDN~W-QKW&itqG|FJl%p#WkNvAqwR{!u9C;9 zYaBy-yiY>Qiuh~6-u0s~pnjKgjfi{Aedc)z#;qvS#8Uo>MSRb7TI_(kap`UmEw3P8 z*B6Isi&AG#!w=?1OpqI+AwsX+1Q(GK!Y@*ycH#ik#kUx&JDF$gaS|Am*Mu%ZHS^8U z%GxG-fuKF0mwLUW^A|#SIMOShl?6z`iK-xS>6Wa+QPL-%$edSQi{lHt@r$@Mq$91nfnRPNjNme*}sQWfR^QL z>c(H?o@~6&Fc8NAft@HlHka9D>0)wcKe2+{Ce_<8h#w~F-+H5*(BE_Px^yAP!}o`< zXP!1y~j`Ce6jBOWXK{QF_DK>e=Hcv3o*_Pf^k$avM8 zZ@zi#00001!fLZkFsV3llYC!M%1(~HHHG-1T%n3W;rE_Oe*CCn2l8ZG6v`bn4$cpr z8ofryA+GlBJQh&xyY@oHMg5lsqQyma#d^Z|kKiF-0~9kSPY`^H2OG*_~%^CFX>QgdeK`|Bhs9C5!3( z?yL1~=#)%!rFfNWH4FnUqGB8-eSZD!7gZmLJ9Cnuc&-R>mXB#&J@?T_eRA@{ z9q!2OGsBoX%EGkDwE2hUl6P!<^~&7BY4qx2G!JnIle?&*(x zYMUkCljffpi*p0in^;dmqt4yi5dPgxqi`00e zesGf?g6Q>r!pM6R@-a$hHinWMBtN%aEMd={sOr&n{i@EQSABr`MWDMkVsyQY1Ef7@ zv`hwZ@>S`eHG0=^lOcan-j5hyTe2vH)Fm$hbWQKIwz0c?nt)CGTGxhdX;IQr$ZpQ! z&zNyZEAg|1d59Qgtg7o9fh{E9mRdoM7YXN$%ew!0@>TSr1(scCano>Lm05&`YrtT&(l8at!mwBKH- zp8q2I?|w{Uweq2t++BI35@#DddPJoEv4 z>AAlM6hs6A3k=?Hj{G+D8C;#LqRL~+m6In@X3q`?{ck zqY=GX)6YzSh;6a0BfvP0x205M;G~os_LiXB`cDwql?jsl+@R-E75c-&J1L_B@B)6v z`L^M#&5B4lLUYboj&?_Ogc{onoq@r4kCDvF-mfENkov8+nOPk6>gnNkIEu9(?REL% zsrdEjl9f-bP5M=nhm`YDgUE0QZM66MFOrO4+v@RfU5>9fyZ|&fq4esK$sGAeJcy`X zn|>0nrLukADNLW}><|y1Bm8wF@%FM~A>s`$S^3y5v^mde_Lu31vS;=g%CPN>;$rtt z@N;#~cJ9A3PS|;??@FnPFv7B@@RJ*B*2IG~dmOM!=gvD}z`i8I`CAyb#Nl4~lt6lHtd)e6`4Fsjj+PlRB(tm&+Rv|H2IC-0m&#&cRnQDk zy*xlB7e%Kj^4m)N$PVAT(2fU1?SS^NpPybARTPg)d8)=DfeS|3XhX)==x0??{gsX@ zY3b6b@eQ?+FAeX2l6PwPFL4GZnp9l24`j7HtG(4DN@1y87_^_4Z;3qvG4C;7dD*^3 z6Y*&*kQLayO}Aq9!sE2>S!%TS=$wff+8f8I3`K&*zw4}JQtE9L`(h#JKQwZPr5qC~gyYz@!d z3t@+;-pq-E3FXgXpyJP7CmuOPy&%+JLho?c1?xD2dxhYBj96 z|I3l&OpYO2sT8O<58`n@>anh*;wgw<0(euNJW9!Jg444`Brqee1KR!}R(3Hj@_hb! zwpw4#qdaG>gLo$=ef!b`W*K|NqqO0tcWX(!>Bu5vetpTS2x|k)HlhI(wr+;_1&H9BE~sQLYIpCxF9Ci+^)oN zQ>7|ZJ0_sNsAvs;7VG9dnjtG3#Bu)vZw(aZ#ZvDY)HP!a_KUTVo;ZYHb3c!?*uzmv zfk0lks0UnX(FHA=X>>F!Em+%0hWB+2IE1ZxK~?2^y^~9{2?F5!EixEBl5Z)GTP#0rIGVLMXT4!nJMc~5~GJ28ss25O!P)rLlM+l9hO%XL+8<65L zbLrPGV!1~C%Dse`P6XWi(w$C;?IFGG2w$aV!Wgfn z>8vDv0IEC!zDG0=#8h7ps7Tq=PSx+4ceEdXRCfBc%c9DTj_Q41e(MG%i=G;l#}}vi z*R9?z@wdQkGB@jYL>?m?JFbB~+B~2BT-FNlE3zHBMwp+;U-58cS05#kwdXRn>u0opsTi65wASOXXk2lAe;=IQ{;e8 zpRQ99mA-<;4u`h)CDUNV?blfa*0d$3C* z?rHVURDRf&5n-b&f_e5vIbr(cVaxtjQ&7zJ7*r_3*kkQ-vY)q~j3GTjol6|m3pidU^2$K*t>uV) zbAg=GSsGr+fHxXNqW$7;P=vBTI;^{6l4;9|sz?)|S>wRc*EpVUL75Y&pJEetU~GY_ z7%aj2p3m<^O?PQ8U4n|9!o#FO95tk$TXPHfn8C zzF{`w+)UWzFV-Q~z-&RzV)}F^i*-GO9O8QSGkuPON4v27MdRm-7&t;~0jfRqeIf}& z%JQssW!|spZz4DR?cY8B?`7ni_hmwKTg8nEd)# zXOcf+x$@rJI0a_77Qe*EE!%{HDPfyy+a3G?x{3-r9=`82ju)6ZtA=b{BK-%-OY(?5 z*&t5g3%flAy zx!y{rhxsZ?JCz1m=P0AV-<#(w1&v=hKBm%Pm#>%2%t9B_Ggb6(9*%T zvZ>HaNlKy|k=CANhgP_9g@xa8d!iTaRVk^!!)4&BEuIRiIr?GQ4*;jbt>`DV%B)t` zL`0cIl*F3V)}fpt#U158X;+#1Km4peZ-S=hrJFK7fT$5~2L!p+Fbk`7Bs8QhGfGE_ ztA2?hnK@o&3KuuQ@uAnOjK=q3?xYoA>D6p7sU&TIi1^8r-tMkd>l!Z>v)+8cM{d^b zZDrl`p7=i3bHU=LAaJT&Ns2rm&pes=^e16eXOpFTEpf-)MMZTEIyCH$SI-BZ@dDor z5e{SrUXZC&W;%r=dV|cno#o)Pn>%!=&*`+F9+=tk095K)VX(yZjtGTj5v7DXUvq5G z^ET|Hm>>+8MKi|6x8=U|8(9=@LK(eZPkF%ms*xM(3LyStv}p`(0it~BpD5d3o%5kO z--1$Hb!6K_2H(oL6RRDq{Ub#w=mM2vtd_SLg`3#wZlmy@!GP=RF0~-^dTI4hsfw`{ zfy}x7wTc`aEo4J?hr9!T(5!Kf0UoJ0zHK!7jFRpGWfTi8f)$by@?zO>AcgrKf|KBz zyP7r_tE!%n`up7jS)T8>`iuRK{w|gT^*L5=ceviD2XM@Jak4aSz#QN@Nq-@RQ^X^a zw7kw;p5dLpv9lSSx3|2DcJtfRG@JvBF@E;(3SsE3?=4s?>C=zC=dp-Rw(yo{$c$** zuqZUMuLvlVF<(%$o|FTl*zv^D!kFGG!<{Tv-Pvw!=VT$!1-5lEzwBe&L|Ij|0#;Kk~9@CT9Yr$x}v zGGF8k-9cxQ#$N3*e*Z_XRIl9i3)kuu&nH8HJNb9M?{pAgtVR#$@}1~1mfzHMu{Q24 zc%_)$idI-$%mf4+ke#;A-9MkmLvjF}B}JLFSa_NporliS3MlyrahAR-Vo3 zXmlzvO9+@(6P*Mg%qx*y{-32vv^Z5tA3$j7Y1i5HN4!^`CZj-HYc#%{;-J$@vZ3y@^yISP*Dufa z7}X$aqmg@+xUThP!FeYkwdI#H8cD$f1h&77^f(-^q5_o2NNLr z$$VyRg#)kKT_U}yu99Pup#20ySn=j*bPp5xKY)b7hZQBQhw8?X zh*oV$a<|_@)?bUUFhpk?&r>ho%aYJao>du>W*(jKUdCy01SOORZ&S0T5aJL?@F&?% z8wOgV`}0LaWxgd{VW(3T0Iekn^gnw!s+|cnA{uqN`d2~uwak3VN-8tLVGjd6>lp7z(dM0f zXM_mY4th#5ol$kMFfEbqRZmBK2ad&AFGQ6VGHX4%a1R?n;2O1ds6e=8s#gh;im9QEKlA$OFImbLDtSe7agcdx9g0$Hi!V@?r6x?k6jIF1%d z6dPVVJ!@BBMWPs_HKlxfk&z;G<6qyJ%)=h*%3&@5F9xzoAN%xhNxZ-3mujhY&UA5( z+lfyD6K$pBjbJ$!>>eD1cem1tA&7hCa_5d%{|YpVa)kYW+^elB*9)9QIzxuz5ayl$ z?;DxYtt4hxvez)Q5bPs3`u`{d*~#iga)WaVxj2`Za;^y}Qn0E}&LWqSL2ke6ua%L7 zVam1f@cx&?cb;gzEE?UT{ZIwj^qLAID0B93L~YPRs({oBKHB4`=S@o***4H|Lrj|@ z3L(GRN8p{-HdoBcv)+_$FN~jg7j`Zt1XlU;s>lMf)i7k1(wSTo5`1HpY5-Fs*@I>5 z(DeT|4?&<#PNRO-mx}vV2^@a)w4U4zGNGz{uZSUX+2_2pY&|^#Rg4(*@M}sHS+!nR&uTw_1y!3R)fD${ncWGr+njod| zqz|%Y5>oepa48VVhx-fZsx-J4N#_K0hRuddP~S7H`^R-fdd7dE0FZU$ zK)UtT>nfIF7VPeB963uGMF8PGG~kNVocO|6gxGQpaST6Oa`Q>=>D_twf|3s>6XiWFT9|4Ra< z-w4Ly;irr@J*s2fBBltAdzigD-E>0`MOC-Qv%7>R@Xm>umZvZfK*ca6{$C07RM||V zzl57WDdL?88uWwuhfb@+p=p$U`u>|*JX4W1>$aY`(VeLKlL9X2aZ5Ey>j=7Ud8XFE z`x1CeIBRyUru94IL_RvU`)GeQ8@ugTCEJ zbrRK~RrG6K6>kx~bGjDln6vTAy#hOuoN*=Jjcqk?%dP%=(^O~l4zq|OOXhk+MZZa8 zMY@!5wZwvrdsq18!J7C@%F*!Prjky+IhaFZHIEyUgX^)mHXx?zm1-|ChSo_}`G#k# zajcB)i4a_cfN~4C|5Y#ntVaGEABFkl=bNbWX$BtcE8OcYz;95y3=Z11Lz+i!6Wg-} zKzds}sbbxxToDk;u!T3-`nr0f2&ZfRXS^%4O55%>Na|76Kpfl#OR9l)2wYca3xSLA z%>Fas&LS)CrVL>-^*nP?oArUvRA|H-6KxJsL?s9};mCIon4MS*x?6_Hb=0XjwCgvs zK6I1c(~-;#ZjgEPCtG2(CfH%)gm^BbN?g4r%|%c#z!u5%ajF4QW+3*(o1)+DnP z=hSkn6|2j7n8@F)syYp0k?QbAyqNs!-iP<8vX)yeq9}V4VvF+p(nGiiMlU?Sb-9x@oOFcD5mk+(p5+M7e#)*Fr(T7b|u|L{&oZ9W$F(}GgF~q zhbHDo{ZBR^i0A2Cn%i5js6!hBm^=sVP3#2GVTZ(5ZWnH#d8KUcUZ#1ua2@pJ1<{0D z0Kx;W&z`93J%Da>m}nn@(a&jm@s7Cw|GT|{(zc8+7abXuq zgrX>H(G2k$k+P10xNTm!;K~@p^!xq^Gx%1Xu-l<~cwQ%#?4~l35_#xeIj1glC*KUs)IVqWRPrq`ipwEB=3kPY zk#f#j-!N9EHK7H#akQR2}jYTDCO7zDj5UqBGCz*B0jFcdzTq6$^?@%KAA$~{w z%xF5;YEs2R`Z~HzkeCLPRUGVrJJk-KD15d$=_62%Cm0K5bWMlkPpvSBeIsmAJ^}rR z1aQrh7}}MW6Zp|y^S#NbWyBWaX@Cs}9nm~nsCc3YZKc)kKwI5w)?YQI(RJ_~!%(qf zP8d1W!J22MF`ivItVUM$jWzf6U{9{SD%!$%)_#XCYP>DY8V$m*Oq&!YHOwkFTKlws zx>78i8QWz7V8i(hFQ4X~rc;oTaKY``Sz&a>HcG+7entP7r1G98G!V9BzVE9bf71tf z&EmuqCYwQC1|oNpwg8B+j^&4~nab#%IXtK^L%?B7KBG@29LckhC9j?>QlzZen?4jj zXg(%on#v`Hs={d4QGPrDalNKQWS=9xrtR2F+i$N$-%02!Y!@UJSX+fIgW6jo4=%3u zc>#%z;dC-T>s$DXbgg%pElzl2|DeJ!T}SMD`bqsL1W3eEb&tfj_BnA+Iu##HnO~{- z7Xm8&=FrG)>S&o9pM~@^{UyU*?rLIOY(2Y`v9!fI-$g>WF8*+uqlD>!UtNCGbJ2jy z75pV&W0ZLr*Lai(bpmvK03k0*suGz$^O0*c4%Q=|lm(ix0=Uin`GPvt;;dQ}zFo{* z8jt`00AGyI_wJSCK|MKLJt9g?JO(0HyUFl(A+Wa%tSt5CVOX{%p{itrJ~~*>ojV%2 zlZEP38fdQP@>fr^{4F*$*^EMGk{f516YyKPucw#;Q>d6Xlzg(w^+;0eA<~@Sr|loB z!$qMl(uoWpv=4TaY_A%Gg3T1o$c2rU!7lzKWjvddRpnPaIP$^4VV$>Az#vfPBxmXt z)*JX&CW>3HAT zbp8_tVzR*LkTHPMooX7fQPM;&bePPkcbcm8`2B^D-)0K=g4S zBRI(VbECdQ-!fe$gOrgOxrrZ8EwSSg*^3{&ht)K6>bV8NCT)K!Z|$4DZ~5ti1}vA=<`PcGimyV4Ons12 z-C#e^R;zsQ(@J5TxvN&V#`Qfk!CA4BFmuh}9XGG)T*%yaS_jDoBh}m@AUVj2KH+xn zokC)^zZ0;1-m<+0+Q@{SYUD-4*-Cb03P5Mc%RPhP9>KODtMVK1b!W3Zn&N@ov55_D zjsSPW%Bj_rQOvYr(l;ewjZi+`(3|q-VZ*f>923miWI57JH%X4TweNJKjH^EQch?N$&a-yKDi>r9X8#{c2{FU3 zUgDeS_(vv~Gr?R(1&R7}!imS?w~sw+*^T#LF3t*#7A^zcR<-I!Ig* zmDyUQoVZ3?i38Xdld{>;P+xnn1@$J$Y{?GBDfwyr)zm~BQ*M#3wdE!FaKe4|WSJf= zS*SKq@}xP^9i-w6DlVi%TnxM#=`tyI2A7aYkD5S{jQnPH6Id1Z@Z`Pn|0U#+_#K?K z3wbaq)EZ6XsMoJ!PvK2F|9!tavi=hwjuNZZp*Kgrmk4wGc7a#qwwXWDb?D18@EU;; zykX=9-DLz@#m*|<5I`}mt2hMiu+(lv>rME54r%-^$W?f?B>1gP7s_>mb+r zX-1sCgcDk2l9pXVkADy>LqET^!$b3-CxXLqeR$led0GwSb8IuwPaegEnz<~NEVCB~Y;OZs9rNLZ8uh(pQW5dGr@ccnQBQUG!rl|D zII}6!;c==PYr=D0am}$w#QM>P(%T5^0Md~)+A~(mgfs@^B<66|?L{uQQ~HTJ7xk|4 zk*9>GN6O2nc7*i2+3UAZZEQzhjM6xYBndyzoT+)6_!7hw<-)5eAwOC||H8XYWnTcgO3BklLw0>L zakhy79>kYSpcWE4Bk~0h_CUc?2rXc9?_pOO3hkjHMYV}dAo;Q) z!-Q$N+LlaHiuuIW6w8|cubG_~IC|}FbT))W-D%8tUdHMI*sr3Dw@CGI~2i~hp(ysEEzS4aI#?e*+^U4O8@R}#|?D}QNeW1 z62L2FFnw!QN+)UP3krcgMTSz80Z}b&cL0|_>0|_ELpo2CcHDR+qozUwqCOuumI&A* zNS{Swdpl?LcYPWy?$uQzO*}>_hVt&l?#y+J^DAn%{Z{!xiqqyDhqrk{l;z*e?d)1s z_?I+3G3X11PqE9(PAgbU&(Bqa=-PuXt(BsIt~(mmrNkEnsCB|KRUjC8*=f)x6)R22 zZ9?>lXQm8D3a}Vdv>1B(nr~ccaNx3tcKmCtczBP!6lyEmh8xFZ?vt6nF#;XeHu9S% zD)-=+o#JN{zx@UcXnc_($O;%-_vfflrh(>nC}u_Mf@-eh$^=|nViIm-^bfQ}5?k#? zp{AXTnb90LZ!vD@AC3H#JT;i+Rwd2?4nY4P;S6Z|*SCT64@D zl8)S_prshvfv9?>q*D+EDr(0tCdbP?;DSm19==J31uP)(SfVq6AVz58Jlo!*E*ms| zGjgb}R3o^SQAj7-+SUd{1;!U~t`EC2ui<^RyO_M$1JH+=zZ=|_pn0*w=y zWcg$*ypb>K3^ji0DE@jTevDKV80x0o>oKj;l<%lm@w8kOKNvK-EPxg)5BAFnhEA7} z_nxn)@mPAc#H%#a$>P2A6!Lcr9}T3!#Fn_4ZQj2lUa%fazAL>{$Q%vzd>e(v*7en_ zs_P((naB-z8BDk^W!l2ESv_Udpxp(yd31mZBU7t?QhDgafZGFH15*+M_vdQM?YEvz zVR1)#8bD=%z~>aO|wG zr^(QMAlzn5*qaR*Qvk$c`hfZ2NOUpMrW>2Eq1rB!K65dpj&vjK+07=+~z7>|o zoaA=sMt61}ea~YKBxtd>opc4~8Kfuor>8blCR$k0tDA7^!$B;l8_T{XCeEDuOwo;D z>J)^7a~A$Hv34_FzRe-_lSE<`m?={R3A?JZn+DG-|7k`dvz28aTz^R`%pYetSrf6e zXVsdolq&$-!i(Bu0?Ndt3NZM(qMy1X-Qe!Z+mBEAYtDC^DGxjc-=5d3L^sxf4KE&@ zr7Ycifsg?iMn{wkuInASkzHTuB?m~1EDS6Klej@0DdN#UY?eoZ?VQH;Q>}f~2ZxbI z$z(?1aP?+z71Xi*GTV>K(&xa>>8J9C>HIkk&M@|`Fjrd**0I1mj)+-=_E!DHf3_f6 z)dz@-)FcU=#4cRh2IO?r`QCCgj@kq+>}{BM!;nEQURSk|G~XnUtZ5*KYvBoomQM!d z5bBPCQ`*i!U?1TLQ=$`WK@oVWI=>l#-@o}iW;&R2 z4-8`UwkZi0KJ8TVBFE2jZ&B!B;_q1Yq1pXFBLklbx$mVGQxa)5=@@?A--xe~Ni^0^ zz+7&Feslw1;(`=>nLF=a*WRfw5CkO(%eb3) zw{`~P14+%h&>M&(hbnmsw|lPOH@j$j*DCC}@b1R_HW`cc;3xqC$Jx5GyzB7-0%|G( z6ATA7i1*+lI^vhny(p!YD1QEY0k#I{GnF!*NyF3me4jQ5%z&30TYG^#&chPo(1$*C z9Y@=s@SqjgB-WyqfXt)q^Soi*b7_)2Cx=7=5EAsazG{ubQPt-64Ve)jj>zmsv;p;j zqMRyWLEav zvm0(9TwocY|0wK_xtD-UI|QHfC(2ox~)P7m%uavHf9_0Aqp;FE%+N?UJS1TlY71 zSmY9ww0i!L)2f%y=Lk;C(&<3}6cPNP9DK(q@}8eyzR+-X7}||B+`a}9L+P$fDj>}V z=Qv=zAqINceRv8GQ&Jal?sq*iBcFJZtdFWrWbiY!akpCIMh`&SZ8j=|S7*7h zBe)y878t2d@#>Xo^F%r6XN>uiM_MMlL>T2Gi1WMlx>oC@^uAyU%?rijD=<7K1d(`= zxYZ#x#$Y4Ys|((1|Ja*2Q_110nYz3D*JqZP{A&< z)c3hRI;&a&rcIf9bN9n6DgxsX5Xc1VF1NQ1BNJX-pWvg;ys=~vvuK+}@ix&i;Gmu& zF!Ho}Zr)Pm&(Te~ERJN-hKg!9hi$KiIVGC z$2Q+$*K`#VQA$e5=%oqQgMOA|H9Nt_7{04(9x&u(Xj4}z`NbX8s4PHQU_XY!JVEK0jgbf@z{?+J8>I99daJs=UY zi)1~Ce5q2=MHXdNTSt~ijGiBK5R*qLPC}lCvA??Sr`H)<^UH}AxO}&_$c+vcut;rc%%%TM7a(QEQxr$u=xgdr8>gNARi7cQo zNf>)Ceu_e4JtH7VopTl8)>(n^zoCxSl++kzECeisrC;A$DU2;&mnRg+b@S33a^>IL z(|O;hjO!y12@?&Sr?2j-f#XSqp!IQt6hfeGkY`{JFsF)iBx}+NyC8EeeyseukMH#& z@s+?2HT&d^)HBr+A7T%g^fDc3~gv;9!7?|K{L0MMv7~kGK>}}ydbO#psecZ zxc8Z|U5g}s4?dFQD1PlNhw;_g*!v3Cz9btnceuyfwC#J{LIh~!-M_?9_H{9qa+&L= zF{+Tmpp4J*>OeQQFp?!QIBYbmoV(Q?2#slyg-XkaBtx`Fx55?CV}d~seznYcOFYOI znx8Gd1R6xm8k97Qy&l)v6$A~S%L`-s$i+nK{ax9WURswn6H9QOlewl-57?38ak1N} z-+Lr136!}bI7m8FxLKA!n$W&-MhBHUEjgG}KzHh#1hwb5O5LJqpvEWD>l+&R-OJtj zGKRb0c$Qd^zM>YUm^9Xi@dc{&OJfXW%@UM52j9iUFd@mXlnN+=rB*1H4&JmJ5Q`B< zym=sE_8qi+Vv9NJTXfQBEckHHluRjd#U}c5yY43XR4KD8NS^SkvN{#T;e(wPJTcZR z;ZXD3{ZCZ*>Pzi)yPmCou540fYqA~dd6Mv{MS%4zu+qeB%o!~1i;g{uRNy@CfW|@3 zsp9=FVH`ki_KG^lRdg2;nYW@~cd5V$V?uQYHr5S|!IZio(3^Sw5h3)hWr+eP%;I7&?5ik=DD#KcQu2p0Uj znx=6V#^;AN7Dx|&$T!XJ0!%^L$CrnSv>GDYWE{7sSj#^K2xkH>&4~FJn2!`WLJ9Tc}op1Paw{3vOV6l3MY6DjfdS#Hy-`+*uC; zbXRLV6R9>!c8pOfNZoeQR+`1t?C>$k)w#q;PGj@29ywcMy0+m#2-Ooof;=-)rc(_A z+D({Qp-TZ)+P#xIJMzMxvNl{|8;_-LM!~W=;%`Ha!NOFwMfP3HSA~pskewQDqGK1Q zPk9eK+A90zDAwg!y{8&7sad{yVI#bYYK3P)<#Xbx41@tT%by}iBcq?SEz8s4_5)pZ zD~+12AT7b+ekpk$-l#{cj|pIJ&}xO3Jy-%x~{ZqoZ2ywM1mSnr!zSFo#Um5zB%h}HF@WHsE|e-%n{ zhZp-{ApF-RombYCrr-@g1(tT&A_!*gUwaUO4NZ#3$ zVb%l!(;_9eE+PYg<<$W*guXh9btuh+A-p@qDUjPwuSm|zZL&j4fLGE-2Ju7y?Im(uQbIFD>n-_g!bkDaIcw|Mx5@T3ORf|SRCmrWlaE2 z#&p^Z)J_j|w#uaBOZxjG;>-)KI;sC_bV4^xKkS^dSX@Kk{5hK%u-os4o4)X(uz0HM zCzaF#f9)5ETR>?>&_L=?bW1wrWJc6b=RBxd>i9e9jR$fF6Whqfe0qt?lQo6iO7{p* zjuW3O%YAJtq`0JjF(UNuU&7>gPq}q%=}BxiqNwA3ZKx67Tjz8zL!~zQy3mv_A*U9F zsf8OZpdOl>^YcVckBw}u98d-h9}u{vodEGJVH2wSOT?EZSwwp#MKI*geFPyF5j-<$ z>fu472M@ZF)5Zk$A7LM(ahU0z93RXbYJ+w~bn-fqOSZbtsRjl%tjKSN9O&jUcxFU` zU;zd0MLAv9UUmhQ$=Ii)KVK+3g^-?~A1l8bIE>0MauynYhC-cssHp&3HF_$1k_bw$ z#OK<~n}|nUnMy}|pH5#$9H|rdW!gV;_5Iu&n(4B3DOLRTFUA}E^hYLJ!fT#Vk)MQ;dI-ylYe=a!6j?9|-2OIOR2PdTv*{)- z-7zdAbi@lP#uEg6TPz6RS;D;}2lq7F)mU+p(c?INO((7FM~)8)pLNL}3fi6=rr7GS z^vIyh5Ze!Ee?T(;4bq_Ke1B2lZKgZfbR+K0mXbpL-;vw-VnG~XwQi)DO zGDXNdD=27z$I0A@kW97-vTG*qZnEmlRgT&T@iz&Cf}I9ooGJ5WT9>-+P|r5z89 zNA|vd_r!R__4rigZt1Gu-1Tc*$dQw7+tRwG6SYjtbHwGDDHhDk;g*u3cFl8p&R$Bq82r$id@YWAY3- ze7y-4LtKz#3Lon-Z&1V>gU2$gU~*aCo!GHe#!2DB^)e)YKNg(i#mCe4mmAIW{?2=0 zGF)scuS=X%LPMvp^d0MTEE%W9BZ@v%C=mnQ!8*TaaO0%(HDlW2LfE8v8(&qCWz*r< z=PZMs8%A8MH8oHc_Hji6L^Un|000Qa;ZzgkPd!9S^ntzLs45C@tVwF>CLd!N5UIvh^ zEwYAKrdDFi*3=~BBQQy!vKG3Tc0o|U`PD=RrxAB#*3udS%?e`Q=}K}>z0)&9Alrur z3*j%?Md_AmoM4Y3&mKwGju6M?ypMvV;)tA;&}e84q<*>Bi8RBa^p2SLdy zf*`AzLK+qf00001=%(@cV}4W3FHIxny%%8y;N8p?F~d^Fuw!6&&%8Uc4=m=Yz6jkc z6XVWNz<)s4VZB~|JS}dC$aIoV0F@20Z?zlc>XT7<3_$W z;^B47wTNzZFa1%n)-zq1_FZLFL8pInigY55m}WX3a50QXJb$7_g`Ay3kSIZyM%y-C z+qP}nwr$(CZQHiHU)#2Ad)^-t6EP99n_T1~SGA~{kyZKKb9}bzu_&+jf|4-B3uRZc zS7Mb+6)ztLa*}Z+l&aX~ihaLELHme!Xrj03=rrF}+~b})G1dG20hvktNfraDyBgoJ zuo2P#Xfi0@u&Pd75}yc{MX(IT%(Vox79btcg1-8?}pmS^Hy_Vv!Cf|U@q0O2MC z>ZOHi1E$a>{W#CQR&~22@gB(KnJ|emODl!XGJ^R4)ogLo{zVu1C8HZ*6lD5AsK?M+ zI51{!Si?@FLT|7+Zy|+>fES(}yy{(I=$CmLJEY3$wihNR93sA_l8Z$~Bfg8ctoHm$ zpv`h*c~%6|AEIv06Gs&@WFvvkz2s40=cnAev24}NE4rdk zwP+Tum-?KZLCu}Hy(-E*F>iGsP%#CLsIy5)CIXcOW-XSs%E4Aw9#B47Nib==k|e zN#YP{D}ZC}lMyt(5Odj&-?~W66hVK2f&?JwC7$b5Ecqn>z&Xo~R07qmN(4rN zRjh=={RP`UMbk|BnUPoh7niUeCs%hk zv}FE2JcSJ>r*ae@5gAGcMCH~`sCbwrpQExS!)xO!+^%lR@k3f(gDY+OH^96l7Z!n2 z)H+|+nTgSP->p6X0E#XD{ND7+4@BG>u?6JiWra$iBb(f58Z<2c>UKM~{cvi=bk5t# zHNW1jIZJk-_%JccZ=gYGn7)pb;gbm zu4bFHJF3?Rp@exA8a!tle<5JJO@@Uqu0CmMbc$MS+szrZoCgfM3Z1Zf7qC}NtAXF8y%-2Ema`3ny?4LGlt|4NyJL$u!)oN-{) zlAx%m)2<60x=iL!gRjDfM>SOCLCRXNPhSm&oqdKOh&XH~0c@9w$qIa*M%5fg;;DTq z`#UwO(QY76&B)-=Nr}E5n|_pBqcn$?$xR>2+jJxl($kPonu*g}={rSDCMw}vzcg4m zTwnStZG>(F&;vi|*leZ3mNMKye1QIZv)Z$N&g-~#OpDKI4K;`zGEA z13h>4=S_;8_cl0JBkGZeCzpcC4(D ztQzPh`-rf!zhU^WX*SJ@o-29b(y!mMb(VWh?I}FL^#fTTTN{)xlev60TgNgwd#ianq$mEr_EU+^^}JP7cScFA+Cc7C%EWeJch#79Ih4w>~b#H5qM(kfV3s z8Ozb-J?w06mq}K){jN1qbES<1cJigiMv#lE>pc>2nBs2Alf!+aYXt-OiJPF7-k-LhDTkIa6&kEQJ*m=_zNjSsG(EcM2#a`S7 z-SdQhQEgf6_R~yiyrhEYPuv%Erm3hS!+Ua1J(Z_npo|B3V$j3~=)yihv-}@;=_B_y z>wo~_@Ut(ffLO}lpbMJQtI5EHslC}BW)AMhvsoOGdySleWjI8-UvI_J&A3HqN=y{_ zxPot&?!dRNS^pt24vc~)V+yV%vcU|G{&UXQS@HJTqg(j0PQ7f%6ys^&reJG-LI7M% z^ChV#v!#x#1=Om^1sitN$d;lRr%HQ6Z+K!FuFp4K)u(4`%XMSQBwrYH(hrpZ)KFCW zLG%&WkWD<*RA9}g{`={Ar4gbpabkHE5OhIn=C|E>w%|4b@3l1|qqcbS;F6Wz!nTUQeRXe?VU#7A&|AvvGA{ifxMQr(lcVVo6(8CQ3kH7L}=nk5fznas`B7s#qRu zvj!5I)w$sp3hP$62mmeHu9;)XJ|eRi5nsPW#G!?2dv$0!|7A@ zd=!PG6n5@6U;X%*wHnM|Im1gVX`!rrOwIUZR_clqF}I_UQN!YDt=W47dg_MbmO+NW zLf1}Ms(XE0jV|hzx*>Qkril^V8oF;~k#DzNe9>U-th*|3E=*nzaH8s>T5j(bZ<#eWWy7?;;zF&|A@YX%JCUBVr3j7j! zRcT?GadfNP92)NP>>X>FdLHPaN{SzEov3HZU|i)sVPMpD8ooTgNZ%>^cZs>WtoMi8G?U`;V7D_-sF!8bUnT_Kx2! z%2+Ygn(W-7+Jg4?y}qlHh|~RDU`AQ3k6{T}XR8x$L#%aUWi5Gpk{A35;aRderE_m$ zL!OB?`f(&E2W*4UE&a_daY9@$XD6cj7~a3wGH!v06I2^~M>@?&>EfD58%%F@zhWkiJ^B zIYSNxZxM|*&Kk@Uhj#`s$<}G*%rG37N7-@~wyw zQYkQhzlw+tc~Y8v6LK??%sllzY~=TG&{7tu#!AawQ5!nZ@6r9x6LrA|7{(o~*#IEH!d)ju^BISnh{2efvOjM;3ahkc{X}X*0?_9d zwX#h^WPOf+^X|Fr8^4_DPS-{C5F{qP$c+V6Q=jcRn34D*d*@v10#P~te!iH5U8O3W z_a>FEleu1AoL(OU<<#2`8T>oZqKR{D5poi6f6}|&=q~t#+v7n!N-#gV|C(Erputgu z2u(T#ZY2xcB^@HDZYhE5Ua)bVF~TaVL@NPs`vqk0U&(ra(UaPzh+j|0Dy6Zke4g07 zvdkJv7SlSx6nkC{H$8ooer3T9whPv`0uh&8rM8TE?m z-B|ukKCNj(YhtPo2DSMV59vcH?MmL3uLWpJAvk+>Ti{g<2)4C;7$Fi=yRC9 z-xzNQ53@8d3lYFnKxU>e2U#KhY`g%Xb1A+7W%b!1m(f&^Faue`k1eRkh=H~qAPZ|FM z3GBx2q4UdoUQ^tvf%?(;g!uV2sa_I_`pzC={Ox*$u10hU5B8W=Gy^);Ac#@H-a^yX ztz~VSAE#j+_?4pV=ZCCrp%_!yvfV91;yu;q?>vpt6G-y6uW>tktE{Zx4{XEtAVqWZ zl*QpTD~r`kZcXgkd~$0p&ADi;A49Kjc$A?fzc$4L`zWvBX{A>zF#Jh`0`hx>X1t(% zB&~*^Tr$n$Ek5rs(Z_3!LrF~gajB(l&=wy%7b&*y3X*-C@=n~cXo+o@V`J-pO_(hA zF0zW#V36-u!J2z;|0F&55bp>{9ddB>rSs5!%1#_thZiGZ%#yl=2P^BN9l`|Bp8tJ_OS_Gb)Oljs zCLqLUQ?A+@U`APF4L!?l%cU5BpPAwmQYS^HLYKtzlmq*mA%WqhQKDO~2 z6%FAIDQqs&XqVzQw$no_T2hNl13euH-qLEXEyeFm3~kHg--gt^-81uN0n#UXNh$J+ zb0IeF0?2x+=;u`bkij_K*a88QdDJ+jkc>&>v(!e9Kjq>85JTVC((MN%Xd|?`jYBqR zH6vkI+d=DT;mml@wcBYS5zS@6H}pe|<9y9c2vPAGds_lEUAL)gpZEDfWGzFc)ypP( zC<}!;^E&4tI}DQfp{PUX{8uHcbwA;$l^=zPov``RVrVbb;v)1i($5|xK(B;vUj%e9 znsm4opup-aKHzptb}z(8_PGdea1!(uZwwS`cV5fScBFWfH~jU@sM`@FU!wG$u=g*x zlh;s;LKa>H$dN~9{@}lSL1-LdKz87ryLsT3eqQDchGYV>4L*szQ-@AsLzs$Y{|adz z&Afh9`4WAPSV&gR8vixfLe-^KV`)! z6&e7rhTx_T1EMh}ROsNwOwpyPoC{LQ1H64cB7kt4MP(0f}d zo~fH=nc0zuotHgPy=|Os#Ooq2SvaHf7&~p+=`N&h6 za8Uav#JFOH{yr6x;MUF&-9{Oqkbr}P`?7&Qf|mp%2oXsb6*{m}N=K0v zf8s)wfDseaW$bMp>G?7$SLwbc=r}GD`fwz*BA&hoap!=!ltZU+%drK$SS>B69rM3= z=jc^$I4xuk$+}uTF55DY>c_o=F1QT8nVFw<#H+zC@{BFq0q2#Q5)ZVe-gWfNG^M;% z*hy3X?-#N7l+-zi?NA(7%Ci!4xAKf3<6Dq#^PY2v9eo-)76 z6`m7zhlQ(F|Fqo6-1hYu6$ZuP5m!F_(QiLgdaYPcsq11-lZZba|3f?zX*-Y?*e^k& z_qPc@nW&BodF`a!+p>~i`SboTdjco^DMrsQlqGcx&U)}^_%E-#~7wqBwTDwMNjx% z@yq0Wq;m3yIiknnl!R2NHfFyjJ@TOJ_t|5q7G@IX;y^S^NvIu40@VuZ8 zTcB@Kyk>u;6tM)JhtvviKHG>s zLb?+ti0M)hcG4rW`n-O48TuyCJ75MQF9rD<(jBmu0!rvq9@;?t; z3WPhCRf_%Dieyr7rjtjTXw-{o1$MMG!ZwGoog|5Ly0t|P zX9H`_A1f}~+%?`HhF@Mz*T!acS&y$xOd#5*_p*UYGQ*PW<3N4(uT^FJDwd=_;G3kodG^laec5tO3?4O%)la2&y?=R^x-igDi!!N5bG^y-v|?&mMX zhU^r;-L813k_zD;U9wSix{JMx<>l8D_=QU5W&%GR=nnI-Q{d++pNQwJ0G+u_IKw2_ z%q5LOI77Kvks+E`k3$nFBu0hp_j(2gcCk$1we~+J7?26Jy^BJw11e4iagB&5;XR^m z-nr7I?$lRC*Z(9c2sAzmv)7RxI8FB}DmzXNSqd@xFW$zi(FV(UPCs0({YmrZ6Pj^3 zFwp{d7~EQ%GB*^?DbtqVsaXVR?|BW!mk!-!;@1GAiD`WV9tKbslOWw zdkqb`vFFeuDfj9SA&9!@vSQ&&I($%2#I^vS3`?9|h@3RRvl%*xS3KZKcCSzs%ASue_rrWLNtGP7@ziq-P(PKHEco0{ zV<=~*BGw#khI|_ughH<0btY_1D-rba&tOGK z0}tl7w1y$DCl(dmTCPxNTHqJ!87!-`mr4(njD1&<%KgO>dfK2lHT~JEQB}qn-%1ZE zWB-$gQ*t;8f6XdN^bJhx>0GGEofp@SP{mpYmUPV)cEt;bqnXbQ+JJ-kr z`O)|Z9wYnDc5n6AR@hYc+=iKjl)Wy9L*=_t#3-8|<5k!w42g+<2ECOj+eHf14tAQJ zz9I|fR&YClVkER)0ocOh=aizUM#PVcG#5N(B(>y&I*(AA_o!U-l@ew>=dM>ZS9{6w zgXKDjk<0lOqk0WgAqRZL{CZ@Z3a%^JT7{)qBopAfS(HLPFteVS*XNVzjY zVHF~4{_;t@3^-ExLC4|XK7E~99fuI1%8Rbp%Ys)>_K0^elgeSCc(E0_Wgw!wLl_j< z=Lbs)>^N(zpCe;c>0`bS`sgH(Sv#Q#+Pu2#sr*FCz}MCR^2ad1y?sD)ePp7G+^+if zOkJQ{$yw^w+@kOXtLyC8MSBn!rS|X3+Spw7B zp`{p?rg{aZgvim)F_g`%%|rUw8q`_1U|=JyrZB`u#T$X2-?K&)^xxZ=&{CAw^vCKN z0D~r?*kEuE-G5@!9|L8Jd)9u`IEXPtUD(wVzuQE|v&m2Cu}B|JWWB32L_>?dc7K?7 zEK0MTzcwW@9!QGOxzQfTSy^gmU8tu>+Yn?K(E4pa6Ey$~$nHGzUiaTO{8meoWs|ij zIjLow^mB#IO8%6*R5&~0YHDS*_Hy+}gDST@!~3p6E`v0^`s6TP@a9GYne|)l$k{NI z0{-Sho4uRrGnn@szW!h?%Na8$UrGiuyel1M=F8)kjUOR>*mN6?Sho`krN#Vvm!csj zd8Q~}6Ons<9p(xQq>FM2`SMdDB!gsSe5QAct0P|apF-FAcU8knFa%R6estXO!}y@~ z1&+ckv#AdSY;Rkq!&pEn!O6h^;9$3V|B_V90?o(B-!s5AK0^LFJ1TA}MsXAx|FohE zVo!x+mF$MFHUzJ-!cIpm27*hY2Pw3J;R7k>pI%Sz-At0sxe*MDk;SvYH*s|r2L@yC z=~e!mS9B;ZYM$gM&D<-H!m36{(wF0Zt+L)lNj~>`N!ddu){0PQ3OOR1(UxpYs?rY` zr-hCW3zgbY;ajYdf6wD0cpi>=Wi-EGaU-N$=5jyEIojnrtggO>XS8imzR`cg|1^kK zTG`W8D#|*l=49 zFyzJorQ<;XhH1*yQC!RVL{jeOQR|NeOsbNC*aKb|-^@NmEOM*(+iRz^vs5DZI~&|q zH3Hvn7pzE?z?;ln8N?=mLd9*nP(_bL)j(@!mn_vEfIq_CAlb4AN!X8wL3sg~QjwFT zWCaz074}N{obs4;0&))xkGs)DHVKOgQ@B@#mLD9iGWy-C?b*6fm4+i1q7;aBNnRvQ zi-Ys-2@EZ2C9J6NIw|NwmG;wWD6tQv9>rey8<(lEl;Hx(Zxl`;k+4suOjxBaQu~w^ zWpdA9AuUEn?=%!+mIzgH;;a+d9;IErP5!c&aA|wk6H6L;uDN%BWx`D>M}vou*v1U8!QA19 zVoF77T0)-`0L2_nqoGg#rA_XE+sShDF=uF37>nJ_4Syp+=BG+~1O~x^+{gD(T_itV z^SH2FC|q!U9pob$9uv15R1O(N7_2``<;d&|`jB`yvSLvJtj>doJj}>LuA{vXMWe+G z?VB+DBDfX8`=9_4l&ydH+AZdm(A;=|3#d zVBDN1pt+O|J6{Wx^~;H8v}9~(S|ump`#ea@MIJs0)U^W|Kyo9EJyGZLm_^gaIM!yf zyk|iGUEuD@cnLHeunp{5CiUO#;O;L|2VaFuSS&=cZ%iH?lF!&2A$I%8NJWm0JO&!R z$6~(#3$VO!zukxqhlQr^wQo%y_AI-h3K)-yTmSo5so`tUEwLo#6ZWY#NiOFjw7<)! zBJTk@dgC;gtC4eL-_Ng)c5Ob$K}ABx32zj^Y|K~XMufSxNw^@%YE>OprtHn>sD8i; zF!f~Z00Z;X78pG0Lc>KkMIFqt`bx>xhYk@4CI*p-mGl6EfCISppoXywwQhT41)Cro zWH+%ru&uR(@mR<3WATT!@6N5ElUJZksR}ov?93+#Qq$-e=@jV_r==Nqq*4AouRit@ z#&42xd#8p3=497O@*lhOvQZ>@)|X^kB<^J)Ig@#>1*vy(T+{1PzF%d#DC3kE{dfx^ z1g&5=Y`9V8;$@v=x)4pb4=T=_W8c;bM}duHZ-Mo>6`FOCG(NIX{FwkZ7#&oQEi_Zt zuLeQ*gJ{3f_czdCN56Weqr8R!>F{Vb7X$b{H~>0@YbRbB`EqQ;yu{uTfIVU6j?>gA zm%8PnU%OO&h$0)6dozrzHl)KEs_~02%>YGZSLPz610=kOCrdBo7D9WF0djIvWD^I7 z3&`meRD{-Ou&q*h0a>ck-YW-F*=--N{%&<^Q-ZYnqqqZ&-llQ2_VF1@2e?A&pqbkW!m z90G0W;fn!XZQU<-Io@nCz9saPgQzrvH)qJ*Nc)_GzD0_N9ZFo2k^2R6!9Aq*88ax} zdfonn8Nr>BZ7sDG^7!4R+z&Zxd5V)u!&WoCiFR0MEU!-Cg5xwblmxv~MiS8YAkHc! z2%QbXmGYH?i-vsZ&id#9XBJDqUXWt504~Y%U`7-q+SNnZv6)$`mCEzM~q4B zhGqCDg~Y*^xMI_ZlpV;%oJ8H^=8cizj*8Ur;dj;KN~rtW{zqi0wD>0{*05#w&vh ztsRTYR{7~_3*J4v%lg2mNw!_(1K;VgC_9ARf@6%yhniQS?2GLplz{(uy{MXzG7M zg<55P<+SX#B#;B7;Q_Um$w<$Z0vywCuN2=jqoSn-MBfXrP{(%~pm^cF9>#Lt$kwH3 z<);6>dqD??3b=~o{Hf$GFn;|V#ke|cA6|ueAH_K{6ae9?bE<-M|8s$Fj2*(Pn^o)c zLNTy@2q#0oB^>>$7>!`v9}BOiZ@PA6pPJ#sM#1D2RObed(Rbv7ioUo4D4>)?me57l zlY&{^#4_4?=cE9f*8B%MO*xEQu%>!EFV{^(-HBw|0RA6V6^huIW6jas@8~)iFO;(P z?R-K>xYO%0GGP=@+xd>^#u^BcW^y`rTWDdyzL|v*@P2-(zQ#Bw|u7w8YpaEkD&OtSSKD%B_$)u z_#!}ObWb$X8v$Iyo7R7gUPk9llyvW30OjAPsrE>KXv1iPQ2;Dx|L>*$nE_)2how8! z5BM|sx=#1C|b6Sc2G_YT*vpkAJkCxwff_X zSS^l)eG|&`bji@9S3UEdn12<-BNnV3YT$3~3;mNC8DFQFo|~oo#qyVPUg;qwhJI3o|w$ zFA68O-Tys3l(0N4x&dv!*1y1`Gmk3%E_vzaE5QDzuMjcAOihc6=xq6TOBa+`jnK1 zQZ*`TTbPh^5Z92WsO6g`>RUR2o(LW)UQNfR4%g^(rU}E=yIbOYGf%KCKfX?mEd4f& z+D7lh$A%Z$wADWAF{*6l(rGV||6;XTn5L1AmxY}$+{@u$)|PjCAr z3+@tBXkP!SrpdX2tHw8t$R@L7#i{!tKx6a3*J&{0UwT~gKb2tjdm(k%oN?8O)!ij> z5nGy-nteOcqyg39!9Q=lEM93~cglQvHX@*4`a@Yw?xIk;(BZOIYz1rZ>=m4(Yg@K` zor(&RLq~KgE=*6jbG3L__?ksRt7D)#E$x zt$Ros!#bBoJ8ee_VFPrV72p4+1Xh9jbxv%k4vD)aiA0NGU$(_sh!ov*PIqw4>AK?F zk31h$8$ievNiF9Ur>s@>kq+&$H7AIy_Z;#UVi?yWn6vv| zdS)!{T`>?mT)^C-lO~?p=ANxmqNq1W8p&^93RFem#hplE{8z|gpa-uFUx8XkdTA%- zZROL2bqLKas#Ry5%ogEKUrqsSJd@6O^U7Q))P6`X{b^-z()Uu?(XH#$#-e3JHp+go z^&~;N@VouR!L3ol+XhnpML|;;EBK^yeW@Q~E>PT4#UvUWSB6s8;YNgjX3}5K!maK7 zWxO#)!!d14fnQKkU4ICRT3P?r>o1-DR%URi(~pE|UgBD(rQ_vQ`6DaG!SqwyF26#K zl*}whBF%gn-*EjvX7c)!M>T;j{6OvfSThPH?hoA-Y85Ks9f5sE?(eyqVWZ_1;;*XH z$6i~RZBGbibjK67c0nktwOdi0NfcYa1eg*%(ly)5Qt|e18Pf|T`h$(YABUsgBIH{U zE4$~MCh^Rd=xHZRz z*y^cCX&XMFXd_=BM*e|62LUOhT>;GP z6+(wHqcVv52jJv3g5T$^(r`9%Pc+ZZxcH0ieDHw1&M~_!y#(079%-AQz5ypcfD~;5 z?mph@I27gwBJ)6&@@Of$?-v*E$l&A(+ z++Syr$he_-oKf8&9>tj+-G0r?3sGSxg9XPO1GbVx7X4H#1JHi<;vt|OX0FX-nb&w( zn|=Rx>2lZ#ccdgE2BY}3=r$)NtRP_X;3j9~17vb`vTu#TvxiF@*yt^C z^jA-`T0f+QUbdd zIYF^#mWPaIcG;PGim=31-I~8#-#=|3#3uHSup#-3io1X6o}=V|XU^EA`4QS`o9QN2 zE8gI};J(g&hs}Pl1a`EqiP+;$9R3Y*yKwJ`|=1k$#510dwk@srj&w9vuvfkTx3#3QmC*Ys;p|Z8+)Aad#8UdVzmU`~# zci)mp@}ntJUg-|I-!Tn4c7}Y~@byBotd%LnDZbkKkKYp|0NBG*l=HtI{@`P7((t6h znVY8ZuP?hTh0x4yBGm2HV+$1FuVneu@YKHy)Z|<=e~brZFAqHwf7jQo^o50JO5Qo6 zM<+2;%-XcSS7y4E=-->;gfF2P{+BgH3uhKXZukKroau6CM&9kNKPO*+7`ub(YbX+` z(Q)6|u?4S3*HW69@@6z>HH!^0s}*yQuSvTUSP}-UKCaeQH6oq)UgksbfeIVtnRuw{?un=wQcInHX^g130W>w?> z;hh)nTe+J;+^TS0LZ@+Cywlgc;w3x;qm;U7O_JMaku#p`xpXw+U|1ssPPqkqsZZ26 z4h(ye)ba)KroCX)s@#QavSg$eyb4*99kxGfR2FC z0t9ia%4GPLotCu?>HHP31o$W!DSfePCsp9*eEVABrFJ{`qVVystw6|}}e;$H5@A8TYU zmy;xR>|evGZH9?K!^Q4|4>%zG-)}g&vW?5u8nbgZ)iRJ_6`xL=@Qe}c zm}46LwuFs{Kd(BP9VjYZx?JLV;N$8uH`Y)NxtZ0Qn}V3@9pCl{b; zbSN-S-0e*HN%p{@e7A!6gU58Yx$%%%D( zn_gBaf&Gz&Kos;0wKcHX+j~wEd@=C`v8VAeS~K{3mnnPlst*FQtyr@W!88OH>bxAo zz9k^rlb{2Eokt4IPTNK^#(ja=q82p9DzA%R^cf$y9RCR>$g#5m{~cq>(GHAi8X=k#3k<`Wzadw0Sl(vZ6&LDdDoUHh`)dA1 z5$NuoTCF4$i4@yEiIF2-6eJZgl=2(&$TWfJ;dCz*N{KsHJ zBMH`DnWZ{M-Fc7vo?0k<5fLQFwbo@4r|!5n9?X=BfdM-~h+wd#(OIV7sgc7ZaEQn9`NyqEQIZv(xatqdz zcDP)`r|#>wqcyaeHvpllGkR6CsF;bRj`Ys4K)priy!gfM`6NT6=A$C5hS_~Ri4o=7 zER|P0-1a#ps}l>_u#am<2rI6-$2ax-u(p53=X^H@dM;exKyOtj!>@%rHXbPw2=0!n z(zp84azNnkKc8Nm(k+$>_P4wSl40Yifg`ike@LZKyo*L>BKrTLW7sx4=OSqFb=@M` zBb{3XSO`tkh#ERQdx6%qnSes=Zkw^0*hZK(_l8-50*X$`0MRDE#eJQ~IUAlH_|z5> zlR(e$B@Mbt-?Y&Z-YApLu8Gmj*OxX!;4iSH6?NEcsnRXB_(XAQtv&K&Pnc8%VYGjD zm4^9;1tAajJH$}K+wOL#Au`9Yu*B;vuGtv4cL_pX5R}_IQ{V90NfsD48 z(G-*oVTTI$=xu<=@lg7ftu9Q5J#ZYsO@bx$P&ia?oSEiurK3@?xNN$}oZ{75O~%>3 zN*2f6aBE>RkmECm*UhN$I$?Iq=C`1GS`(8pp)&`;9{pqITjwe@Xsqbv=~nIWA~JQz@VxiZMmzJkxps-5|tL07^vc zI@oA{q3*qsxaYbov%1 z{s8+Fcza4)EAug#UsSxh0^eHPLsfL7QB0eLges{#^FNV#qo}HhSEtiKbE#cV{&^vt z(sRC`sCU^&4t1?NJ z%%8uXSWqyMj%z3HYXued_rj(tY*b=rb#er@Gl^HoQ>^E6vzE}V5H?x*-2b8Uji@FI zkBA*^w>A8C{eB5nm>>DIWUkgwT}1kHl1cvO+C4Hz!g5%$Z73r#UNnKFrw6QdjGz;Iim?Do%(?a9Ra7+RO&iM zwT;u2e-LA~CUxx(Yh)JqfX!JQuisgj(BUswFmXHmC%i4U%y*k zQ?~~3TS*a?TWPz60n8acNV1CoQ%tc3Mk$)L-q)L}W!Qf$0e7=rJkDIri0XNWFSaBm)joR&TLo3cr>a-LHDgjVXmv_(>d;j;GBG0%@X| z3kym#>(xDmyFb?$m-Flf0TOfdFMuOyjI6S~Hw!m<%W1G(??EpT#_HsoI-{&Jw@L|x zP~@H=zzJA$M%MP<#&dkiW$psn2@P-#|Q-i`2CP@)FxddMO42iT;TJZU}ty(`mL30?8Uqyuvo*$wuRPYz? z3Zx8>yqs^)<0Z2N{=EHEV-ZNXw8_B#%RAQb z>uPE$Gfm`e+a^$EYu~8NY!67bTpT+h7gX)HB-K8;S~J0`ZKuws{^Z6Yz)Kl+ znOkfLKb5(x4MHg!@8A0rc!=g~=cH66%4gvBaLzLIb~oZYZgFBUj?)ePNL3=Fcn;dR zyi66UFz!$(h5e?1u5GoYwoZeUJP4ubGl%_zX7r(FlS~wfWfhcQ$^=;yV+V5FDwG+F zh7|FGI1}m)h(&$Yfq6E}j1N_eFwFvbBJzuLpcNwxR^6F+Cdb!`nQsXjn_a=egB2%{ zl^miu_8aq=bd9y5--f@oD2*upY&@D%+v6_5k}O!S__@{bgN`2|se58G(gi>)sM zUj7#VcR+~0s5kIpv`eY<7TR<9@6DZD@6L#mnS$g&cNU5(&*}Ssirp%VF7vGs;QRcW z$CW?5TS@wzH&mQ!h7#;;R!S&K`c}wb?%tYmK0x>vL4+7LHm9)@vw#B283}VmJhR-> zIG;=ByN!H++Qt?%S1XWy73!)NSCBJ>3Lv(|tcMc-e>4Wm2;!7RM`k|*z3ALCQo81U z7FY2kX5!$7Zm6sRZF-l}16P(Qh&(;vV1C)>vTOWqJrRP~E+nG7^p)!h#7QioN9)6) zSh#B@VkPU&xw#buNr}2c5zu;9oVf+oz|=ZjbBx04@lZ)TvG9V{=^fM!!{pC1;p?@)!L_Fl`!@a6$q_I~%1T=Br#IBmY}))UNuFLip%SPBa58_S@`3?m2ulB|R| zpBf`e`uJ9db8p>9VMkBj@tw4p_@0ZyM>B|&{LxtZs)`zJKgQlNiyBLM7fh4hJ&?2k zDIUafb62#(GRl4#737rp2(v}!W#tnjXUHeN8W{O|h0nT@1!yi;%AKjc}dA*=L`AABTF5=+;1 zLEYRi)y&wo9;TBBR_2gf|NhI^`i^>rAM+Wk$nBfMZ?m*n-XMFZX!bS)v`bVGN9 zRxwF>Tl2L`kH(ax3+0>Z5BXews+a(@va;Qc6J8kRsPt+((MFEw_|1WMd+$gHV7C}h zw!~~2178g#7g1&%uriM`pW^Szr!Wz#QhcN@pyOGg0I2lNZwP1A3%Q*6TV-76LE@9P z^KqA5u(G%SGm$51!vj_Lz~9x>9#fS#fxcxSld$>%F$g3>C2=V$CU2@jto4he^~Glp z7BV=?1Toh>N;_QdaLEab3_4q)>HsH=-aIy*bG&0ThWT+%$#p`bk6=Vw*Q=+ST-4SZ z=A@x&BZ-*}(B{GMwF5RshekP`0^BzX)^0C1uB~b^=$F*xozfEYta3Ozq>_(SA4iZs z6;y2g3g2(J(+a*(hPRl;aUAK)cV5L4%}7f`Da1jh3`y<;=+|g9`r%?rU{GOJ2<>PC zW&+Rw*O=YmdujNbbX^hRtagGm5o{!FEmU8LloT6fF#qYbn;U~tx$wgMq)8#cAxe|5 z9N@D$mcr)Z|9LCQzplAA6afKQ3kdCbDkcV5Xn=eho@9E06rz!R4`<>s#`& z!E{9I-`{}UTr^M02X5{!=4Ht)hGfTfq<%tWdLx(dr(}=IPMKQWp&0h|6o$PT8CKu< zAG9Zcf9;3ew@KP)@Cuv{BeFjoOTt_>a!l9;mXHjZO)OYT?Ip3D#(yy{O z`Q%&gDAe$0Zn3lt1}-c z@vCF^1619UJNJ0~_v?I_wDOa1bEQ2V-c#dg=MK1OjLUh234v^cp7V;FHcK=|FUx%u zg|Qn4A@2>8V)3CF|6NnJhrSPkO0=94(Sv~OEG5|(EIf+i^$U4a?3{jK3)Y%4xdo+h zYZ_%l{7!5|e}v~;4@5FVPxIj+2KOF<06ORJ6^5O#LK$PMF6(E3u^n4I@&bSpV!P~a zIEIUiIC6cPk~<~DBYnIRL%nBB&pxeuzry$nCi8`MoEA2$q6V=)G=hDH86J9*770I5 z@+FLAw0>*03GcMKRvWZH(kCT=%Sy-71I&Ifof6NV5OeDy40kvhxl9?p$=h=*MwX*_!?eI+dx?2@@aoI{~k`UH%Q9QtZ+GSEXFbJrz*Do#Q@;k|a z)?rx!7dc1y{j&t-L!l}nfw&tmN94}I-1T@z00S#0{HOv?@Jhy}t)RpU4K-RaP$(t6 z%)@RGph4v9w$jKNvLjVG5{NS~F_=O|Vp#TR`jf0kn(kpzcWC zfYkaJ{6(`aWyC+quZrsMnIq`+o(SNjBf9X30N;Z8Bl0eLh*>oT43d?BN#LNtLqS0y z5SOAIjXz8nis+EvKA|L?&H$Y1HJ?Z{eN{MAG$Zxq`M7;`4A^Gf4=f$9Hm;l3g3Zza zdS;WFjwNqaXS}zYB!jk^?rz}BxM=+bQOgfR95yxuTVP-Ft;9OFM92au zJDrUS)yCN~{icWYt50@YNqY8Dx8&JAiIm1nz_FTQFH=^YuJu^Bef=2#Go3ki zS)}5xFhPm1k}Y{4Cydn+Q@EeIY=|46>GO~E%d5u**)N!Z`Y#=~juFI*&S!MYbpytbr@Bb{Gl0{-*pQpw@2~9@Rr3`nVjPGdUtE57fQ#WBW)LKMd?& z+$I(w`Y*ZmwQLcWx&A8a?hh)$rMG8}H-itcIf&bP&JwS46>LNJ-ZA=Vzz|_F<&)+X z4x;h*KUG^0fwqM4g+7(1)5@>)5gAa$D5d8#VlirI6y%|3lY4}69_nHn37yzRZ}EIV zu2bcO4Kr3AU@%;60Bc@#D#^l?IuP2eYyJAL4E(!cWIvH++d#EZR4sAsSIX0admBVM zWXZ15|7!LFHuXi?6kXHD7}G?@A6Ka(Majo3bO#A-as~=kV6J+VYdi7dw!6`H^|D-YPu!+$D*@|^)UDVQOiPOpm+;@_*U==cfk)!F zKI2LWyX@+iVskuH*5fz+w4L6Tt)vwtLKvu&gM1!-Wj(s0&gYUlQj8k74O{be^Trs2 z-hXO+8uzB059wPWdk>Gt#w7DG1*`~*uCC2Z^Iy3zjAumdw`mMu(=eI$z^nnpm`m2e z%C4KxV|W~#rs4QP|G(NK+B^ypXwS&j=c(G)GFbpQE)Gd7)Y!fXWYafG_ec7AW_~!J zOs0OuHiV{9Jy{}Z-vre6R23rO@|dAS80#(%(s9q+)Ghqy_#k>d?b5@N=xjJ1w>Ls* zCQKAPYgIu21$u7wPAmk(>U2~gP;*SB1w9Pc&zb+}uqlt-jg1 zF|=NfAF5Pz3nMWV>UySy9f?0J3#-5ln233-7(zNQvF7T*8YUK+<-^Hg))yFYlG6xC zKD`X7sG@1fz-T~&3A2+Sv__>VfK!*&M7uf{+60_q3E&+Zzu{+fs4@S9uL>S^8e{*c zP88=zdNhk&6qhIg69}^Mvz=7Lb&&+=#fpR_%>43{T&Yt!l!NhvGfU|Wi4J{ei{r$%tp#3oPXUf(BK}~T ztayGyqk1(cViJBobv!7I9~nLJoX$7xY1_fUTMhZ%;AaJ^69RKsYs|E4Ze|01es^>Kfe}JFfcj`YBj#98_)}wdZ7?EsLSWyaL;O{Rw zTrtGL`wx)y?cZx^c<+N~qMKf(IpXn`lL~V{(?vKb!zkI61HIpf1L(IH9P$wo!*>Ib zVhkUKx|1c2aQ9HMz^8?qk-5qmf;(($)(daCtY~hrDlxvy?x&ZoqefQm0!xGm0rEOM z!(}gd*1bQNM|-Az-VlbI4HT7**TV;C%^JY=_Gp86Px>KEPr4ey?$b?E=zo53naA< zW}wVUear3vz2!Iig?6yD{oMJgUZ9O`&IrVFdp#EypO+1wbT%c#%=B?z%~p2&Yh#u< z5|{!*?8YF${MlFbFUntdG~Yv~6L!&5#Ygo<(Ta-65CJ}PtVrc61fEs3HqC4dDK}1q z8VUJ_Y^A_ZAu(OJlw*wHN0L^G;n$D7wY^U{*pG-#cTX@!v1w7E#@+yFJC(tG`s=a< zcn3r^)u6e7nzSwx>1@lyN}pTGO?G zoDzV6Ps6w6gmPff9lkDCJzW+wVt60_A+U0nxDEmGGa{3* z$?7=0Q8^M?QnwEdZL5+8@&s}<7Ywzt zp3C!uw$mQbJZcjkLYfFbRQXEMaYdA4LVLW9C?B@p1|$C+-F5V3Yp1|gP6a*=(OAw! zvK#o0l=>=NRqa*35a#X8d=|H473;7=$h>BS@B=l6kcHO001oxo(6r*e~yMY^T2U# z11=!ObXJ__Un;><_5cN}A+%w=c9*3_Gjk?h<2RCP*o%TpmKeT&QY97%nTHfsjMCd= zl)GNh@VmU{TeyMaoey~nntLNJ}_lf?Bc=R!5 zMB+BW0kM7pLrr%f{r+ky9gdwVdD7$@wjqUsW2#e(Dj{}UkGLKIV1R}yXhvw zUwYLR6kWUUkF^@)k>NJG6<$M<1NJ^)SOU4alj8VlX-PH_WVcUm?8R51rvS;x&VNB>5cv8HG0YGiW+HmPa)m zw|r8PnqR`5B)eX=SDZiq00dB*EaZ>{eWlG}4g?*YtUDVmYk@H^gQ)r22L0qw+Y#AM ziGsLVNMHNx%y4H3qcIBCt^I(GKu}ucS?u(F&t8NLT3bFJi>)xJ9KQ{J_31p&#yabhUjgBp149-iG>iIMb7w?$lL0(4d zA=!HOyB&x0y?iYg2byM|^QPyYCw_8vg5;b@4GPRlyk!`-yu-SfebiC>^fd#>JYW*w zKTI8DWgb0gj*~XzBJPWs3C8es%o`McwS7>Vp|AZdcCbu3YVhz^JpOc3yda;FiA%?~ z!!h14k??0f`!o>W*p6!(nt{%_=GEf1O77V_O`B^}YS-Hvj;}vxu}sM<0!7W~`Xk_v z&dtFZLQXt}--+b;>dB6@^CPP4yXJs^k@IjIya-W;zb^ZFhU zlIMFV_^k0N+K}zPPusL7?&@}qFpN(r#PPvA^#J$B9!1(4vQz3@3Ew6@ zB=U;Cu3mUdI=gcyFCzNBfT_bDXQm8&N2~KHao?9=5ug#u{?OgG!+1T<&X&M<*}drj z&(Yz}j0`nMo}t}}HYS4_fsQNBe%mTMgTm=;04KOGG^)y~TizuT!ja97mgP9-xUZk5 z25)I+X~s6<*rO_UYMz&v4k>Jzv+`A!sK80KcH#=}n#p{;*t*Rd2uB&vl=Mwr{7-cbOO&8ZhA_%9jIa#v~z$i+zJ z&qUiTzAa?zRnv$xz|Fw=!LDmq1EG*vzc~_g~|OeF>%AIeK|^d2X_f<<_nyLy5p)N-vpYxa?5Qa88q56&O7}&$F*i z7&VzRTW8H2!jTazr5XXwEn?)a)iFn$wBz8Y_}_$6<8aIcqqF{I5QvmoE$9*qKbvh5 zG;njh3iH6MFBq^~fK?C0n_2eKjee??r7(Z>Ydiz$2;IWqi_ibdNmIJek425Gjo5?D z7YkvXvbWHOJ09ZK($U3iTAKqyxmKlaS!^K5ivTu>@n!8mqk0iWy&dXcY(y*Hbtnjw z)?kEh_Q@|7nHr$jG8%{Pcm^EJHht)sdQI?lH6d1I{;cq29DG-0|&%%31whVw99Eor_cZG0oEeZ9yrvqadMyu5uo*dGZH>T?@99A+p9) zNiUV8pZlZYzJP1}EXwfa?I;&;I1DLZ;&cLW0BAe;yqFbWB)!?eha*M$)Af%MMv2Wy z97WRFgnlLy7-#)*GGeyU7lQ*w;hh(k@zr_!Lia?MSuM*r>-hdY zS$8=7c+xsPANi^IPeElMJAT4?O{mR0#M9!M#4S;~SmG+Q)6D6 zt1&hhK!Z;@w7l{6a%YGKWU+`*5r}Ns^y%VAfRcXO5;M6yo<39#XGb0eFs9`S);HIu zZ%uVPykTeoc$~EvYy`|}`J*DDAOHWIdUw^fjgQThhE;Z*2lcGh6J0x_VD=~iA z405AXNsTns!&8B|rQSeCXNz8^IS0Q_FEcHJsxrq17RhNgXdun0*<6|L{oRpGxa;d_ z(toxDZOt~(x>lYG8j+eq(}?$}@w=gXj`3P?1|_gNk~OCKFrM&L!uz)i*#R~CMOaNL zch#~TC%XgN@f6Nx6U2Pny|;0_ERR5i$4pA(7u*mD^lRp-le^u|5dkC6VCf^+1PAmq>~bQF=^;IFLz z{yY6$9q25Zfp1cwX0Sxb;9pTmXzf?M$+X3QxG$BX7K5Tr7qg0t=OK?~&ntO;&{FSn zUU~Yze6D{g=V7mPZ%iaWZ72`+_gu&(+5S$(;R*Vy2y6!&rHwsb_z`cWrRC@wjn~uc zye}z3U_C}R{e>GU64hA)i18H<)k)&`aDDu#{7nu2TL`rjhSr1^RQFYZ0j!6XFA4Mh zDqFW>yA8(uIv~Uu=v(bCLn(-rTnX%`X(W*fobxOAG_B!%IXYGLVO%_&!D=(58~8%g zSlSuFmzMWHdt%YMQt@KG=%_RKEviQwGMY~n zjftUJ1pyfcaa?>9t`(8rA*^qVKS*jfI^Gwq;*{`nQ?ynx(?Q*-uB*(2jm}H#7V>(J za?{6z14KP_+U>*8t^9{e1J=UX@3c+x(EnLAM|c`II;myg00vO6jb~bqP31q71cjrE z&Y`{&JHa|A3AW9Crxa&)VG5{NS~@At%BQ3(RMTzR%TjEv z`P4{pk;Mtu7M|~0>xi3sKnBiY6Wn(Y03}z&a?oKBAIZ~Xzs&r8y&e|1Q!8EV>X6Ii zp>HcOfw^cEkaW3%_XCMT6g_>G!U6(aDk?QnhN^&(J^Q*u+b7(+JTbX}d47)0`b_%z zx$f$yi2wJIr&Z1|&p?P(L#xr0DqSdbF3matOcg!cqVs=M>OP zI((at#r8io*4j}iDcf6!$5!9qrTBGK^I(GXhO9MoAct~tk`xgXkJHq%Fuwg1n zFK_9-ri4R^OA);IvsRfo){_A|)3&b$ZAx1?)yS};NCiE6c4E{XI;PvhTUA(rh3n-x z?>{V6PCEW;mJr0Myet9cIAfc95Y*j@-h%*tAiX74&v(|ZaU_i!)B<^iNUQUa@Kz=6 zvBX4M7l-gT8P5s2iO&7{hnHxM2yPP%-nR2omjyU;f2ZGcF2r%A5xaMuEOiIUHL7gk zeVN}g9Vyn25tb!m-7Y>Z`MEirii_%GFJ^X1%HQhy8 zt@hZmI_vRY|E1vk@3%$QCl4;s!boy63J4kMY9rvs$}Yn-K9A@`=cNa{tgSt)S5rA9 z?$z%p#x5$%M>aF|sW=7}tAuT9UE91Qq@#tp6JBtTkL;qBKj=f!A-!T{zbVVWH_RGO zO9#`4x)g$G2A6opwY1i?slkLOi-yd$2XT_?xR>|b*LhDrK0KfQBdfWurIglJXBbpF z%=F!fel7UT>$)kMj!e?5>hOIpZpI0qBLC3EOUJGD^aNWU#>t!J$hsdoV-eUIIH>Y0 z@wM}xrK%dJoN5S5sif&-D$l|KcP&T^!P*JOablpEQ-{KQBWsbX!i#AHbF)K@alfc8 zHPm*D$gjqpQ4|Vdf0Z%S;}RrB#=TJ$@4$fDR{^)EnoS^KN0_l<+&5w8z+zbh56c~u z*-R6FQ;jFG!iXjxTPxLDTuX_;Cu%KcrN{nQa3;gSU!WYBd-`TN-BAg{`_`qKj1N%^ zJhBg;U+*Gs@cY_J%0Mc4fo;d4sK(1vWy!p^wRydMePY>1+OYu>-u2kzA@S3=azF_x zGBZ<F^V&lGtcWvPj(%Z7FPNj+11?sSrAa>Pf80oqt1M z4fqbD4TAXUgPZh(%^1ot>IkH^5L{Rx#A~jfE2@03_EDzXJAvN=oqMD$&F~ojLdkl- zBZGYp${3nv{*# zo}hf^>Le#sxYHpPawnwtkN@n7S6=Jpc0*`}RJT23$Z$jG{#9dY2_|Rsqa}Tr)@BvS z2EJ$ShGD%bWlH|z=Iz`o(=bygEkMAK7h|K2PvMFPb4EWjAIsLZm~UNZlNZE1+?)K0 zb~pvR$ZyM-CO`fmrMcyPSRYUvEcURgwioE&g@0LkUYO6D;nlh?qZjDe-+1h|2pspp z0|US#?!$98>(S0sv-_S*F_hT5>y_p-@1{u}u#v|;`Re?r=p5%bZetz;6(r6kC=3R7 zuA`N8XNLG!heIy$r~ukg{}JKJYbr{%<-c&hw%2jREJYDme=`Mz?4JpWL$F2(RvBo6pM40YArYrgAfs7YN8hk2C+ZM*Z-HV64$#Nc6XzzcygkWUz166c)n%H+qK4@Do z!G|x29U**9|JW16wDMPTzbxh|IpE(VON`ckXtRuN=*|gjpruU}^LV^6Qq=^Q2Kbz% z;cCrrz6=3FLkLZIzceo4@%mFRvwmB?T>FjH5eYNLRw{|!Ip%j~jnuTtj5pbI}B)T9wH3*;?Qf;TG(C@-t0Vn+$7lBrvEp;$;1KPXu;>b19%;HW4Su&IE+8 zP)g>0qg|WqjF7PNd~p~95^%=Oy2NQ)vX?{iS+t6KM=;Xmcoxnh!$~w2<(8ayLN;dR zocl~$pxm8bFZwr6x@4NN5Z5)=R&zC5L8Z9hX|7IRVMenUx&@3Ta=Sa2Q;Nz!d%$9P zL16hj0q%+%Ek>8%J?U4p=sBz){la2MO^C5435 zB36<|T~zs5_sSUq#TQpJ@HJLcGZ^#nzCM(iy+~`4M-ye<{&`WVjTOw0S@nH~U=oK;}wj>a%cOOV9r|u%f zGe1xc@qabBBQ=5jpZr)H{ut{6#4VXuTlo1|woI~#S4|(ZdRV^HF=m3&>=}cO?&);) zRVsn9(1K*8yiNu{@J0T(ejG{gqa!9c&Rq9>aTr!xeOCB)w&HBDVC{-LwGG=SUyipr zle!eIdf{S&lB`W!rZtgIiUN%%JaO)j@C`fyfm;mKVxxU~cvdrFJRT89R)&8{^ycv63N|LD9q zwS`tZ@M(1`4J&$}Xwmq=RMnJ}*h1?h>epX57Tt=#jbPgp*Kk7XB-@tV7^}4GTSue& z3Rt1sP@G;^Ub2?dR(yUBn2!((9GOzvj(gIggXa<|s&lp%^=*lRpYA8jbN^A1?7<m43 zAsfL>xX6D3bpNo&IV~zdbomYc#gJaSItKINYXVrYNoS87N6g^pn9aoT!qgl7?z;Ju z^eUY+0=GPn0`@WLyK7c?!H4-Zedl*c!HCW+;V>1>T#Qs5@}TgIKWE8-HW&l7^SUuN z1@@N4`~|OrKBL9WPEld)|4p3fV{l4I2Nj7K-rg}lyDboQe$XY00y2&~{FpFkQh|CQ zn?fYVTkwAdAwT?kdfcY;B#-_6Y4s@pImrUnRLzS4HA1oPtX#VOs1=w@SL;NBy;yc=9=OKAa8ao@t_&tt@gVauw0C-}h2i zc--R`{ctcjW^C4S8%X`5PY~}16HSZc|)}yLA(T-EFd|ITHT9$oQYrionnb zL4@rfy3cM?0Z2t9@aAl4!*9MGZ7AgKDZOG#r|+fyL0Q0b`g%3ME$( zT!hcu_c+ADqu)-?vXb_ncRlM=({$N>oyzw7k5z8Ob8m23)VQ0$2~G^fzxCh_mTQvC zO(3wh|qM`x@U(qTPn3iiXRik?4V}%3^JvBC_#qSwTA;{c5u1f_K zZd<|}x}2Nv9S!W`#^Bs4Of{sPVqWxzNgrc+b^;PJGp29vrLZxe=KxXMCo*n3~RnH`nc})ptj~t#nwJD9Y{JRSND22S|cmAssM(`~t zVJixDH}qv}p+db|e|KnKy*`Z+&i(wQsc1`Q<*=nTGV?#<4;rn3+~8Sc=^GfRN`kl7 zX&Daov*X_ZewX89w_S|VIqiwzNxjFQfDXe$Wq6k!Wv?!r{gge54{M1KbbDnX|LyW*r{wn%r)_h=k?-_@b}v=Bw0e;5o#SR z3Xj$^0#fDWA@IfS9(G$f*g&KD;j&G?oAGyHp_<=<#f@KA{&icvZ-lnLI5E^xk)r*a zLIvchBZzVktBURHyH8DW6hy(#&Tzg6kO1{aG}iXNAxwd?L^0`}zzAsgY#iGZ@w`KU z$mwFKN>LqWKxy$yv~|D_a;o=?nl<|x)OFh|zXHTdaS1yLRH=|3a#BB{pmIrFuNc+n z3_%1tyOaslc`|zXvj;6}f}DNx6~%Uod5yJ&a6=e%c)ZN&MJyAnZ=oaFZsyXz~5XM05O5`wML8(q9~a=o{!T0?S_k9U-Y0ZrxbJ4$eB#YSG3pqjusn4d zrrncl!Jc)vqNli@uI;bLekiikQK``Qtm;RV1~J%K$cVJ*R<#AF6HY$`l4k2tmMkuf zTC~RR_22NYCxDjqWiFSZTGUDj0>zoS`cV29hYLE-_WgYPz8HQR_pNezG8=zcq4OWt z2unbWQqnVcu4hJ;n*R_5Syan>gj1pNXigGyXsK{-W8r!hupBnvW`TbYIFD|DLAtK^ z$XR;9FEi`gldARLCo<9nE}u<@Hb1KjyxExz4k1#EFjiuTcT_8XTz-9lOnZP7k(@|Z zhUQXyzzkc?rwB3Kme2KG>I(-L@bz+Qzv5m&+h1FAD2aD5cf7_+2)ly(X=mStTHeNX zy0WBXaI5#IQ25V{ZA_x5AW9pqQ6WG!eXxJzZ&IsyR+%#vR&<;5U?6{pcwp?A2PM`ewwd|_u z;eG;mFdx36XUw)SeoLohz-*AOd*&%K1&Dw)|DUdWJih8)+Bia%lDB@I1{c+U%`mc9 z47eED8i0%4pxdyYmZ+(vMViB@ z;km0i$%7D>B*1PH9~CM){u%Q|uuA+vQl2IvHdR#UK|*R*Um-*U*h@UM?twdRxvQ=7 ze0F0UTI0KbgG*6Bk>15tyw25xEjWqr3k~v&P;KCT`WLy6ZZ4Rua$h~(|Bw2*4- z=o+<9M73`OkzqJe(d1%pQTN;jxFi)I=h((vOaNSH=)Hx(Rq zR--ZhVEtJvJs%K))RHXZ_<{^sL6*WBiGq%o#|ZI}>mRy5Z~(?u_JPeVL!|gb+wN*K zYAG)ZJ)k6rm5eqWHOcwrrHEBrwzOdEAugU5aO^~Pbi24HA;fFK`<%3fl>N-Xfg7ok z>4z&$gY)vx{<;}%mTkE0-I$Dc*uLPJ?g1A0$BE-Oc*PNdYDjvXca#~0D87I^=x%kZ zXg#;OJ7{oiDqO?MEe-N~Vg$RDk%|pode9GQq=)8;K>cp$cQd^W2Ap%h;>O(9!&Ws_ z3ZJU$f;j+sZOUUWYQ)0uXUZfAu#IR{0&>+f=ADE==ivtQ(F{D{n?^m8C}LQXN=@4>r=aq4zD>Q!$VtyLK-BQmdgS|4u(P z;<224Y~g`N6Y>_?ZOp#ri{U@3ocGFW6=;C!I@YMpLJCf6{l(k`%FX-n$_Pmf59vHE z?2V>7dt*mvjoSt)gk+Dm5a9iVt!u_fP`1G+XP<#rmn|y?j5og;9&}_j`k}5bpCilURRDu&%?5_LVR1*sM5KP_M5xkVGa5jk{-w^<8P+3o3)xC?x8I_LYj(++|Lnj@+x zQ9SIUr#22%0~u?h8$x(AE;V^@+ungz<1c#=AosTIFN86ae((Y6&oef-d1KS5$j)j2 zJhEb#Jz1SJRkJp3XE%IFGnYBP!|@=8o;%dn4-=kaxF{9q1)M0rsIh zE#kTPt&KEJn!9a_3wC!MDoBd5NqqGtT6Yi-?IPgh0CT<8VqqY7X4#orOO_#98R3T| z1gEik83!qe%()=X{3XaPk?yMl_r5iXF5{~`;8poDC9e8Qjj&u|og9!RJd;H-cAVk| zX_}0_nTsRa&&93+ok;*w*RBMXDM%I=jr1~g0m%|3YXx@yD^r2m&9<#2beZt_yj8hT zs%yESoVC0mlzbsz6yCO(?k&R_RuJ!u-LOy@yk(tEd<674pK^Ci~m$_`jo zN0s;7~3UU8QVWy zB$KnZ4=#YqPYD|F+J@biX)6A03S+7iU2A-%&%~D@iwE(OIM3AnkeB;?g^Rk^8rm>~ zmxu+nt{L=xumwI+DhHoyf>l*om`Gq!0OKhE_1ta%RBm>-D&BlJw$R!pPhs!0)lQ(A zAb(h{W-RZD8iMpY;ZWm06G9;CtpY)h4;mU=x;JU)tX9DUYg>^Xi%E#9FER5b%?|e1 z&*5oF_zU-I5qcDvG1(82%dmt#C6S+Jo74NKSM!Qxrm&Il0(a5^3~SM#DY1_sM_W1p zY)+Mjr6khbV^pVKW{EmynZ`}J*KG?4IH(0dk5@jGp;za&Wzl|yFFx}cQ}8VibbwRe z>JPDt29b}KgxID7!G;eA0HrWkN{nSn&0kFv5{lHQ-Ekjpv@G*J%(x2{USVnE|A4x6 zN}6K-Qrv4=+}m$TW9mBez;EJI>Xy*YB_3w(DMJ|GSDfVkT58)<#Ock#ZxRS~`Imd) zPwD;iLVqlh^lJ5bMs8-sLfWy$6hOK%;x1(+*z+om(|smOH;@6>YU^Wl;AsffebPk6 z5{`9&4y=AdO?~x!IMjw{yde~*DSAAEG9cZbIT;;ILjL_M^*j7Sm14lh>eDW0woC$a)#xaDi+iS z-XPrttgsRO5I?4~1dFK5y7ZjJ;<-GlZl1Ov#*{bespK3821U~UGd9HmsP2vh zHD|25wSbuPd3t3O-8lkC{$OEq`jc?SCY(TOb1zXWMfsJFAl5nKY%a^X3ThKT{_<@} z`1omeatq(t5@s)0^A`~Ac>}!L78?v0ec7G?hESPiJ zC-PK8C&Rapap_8HFD%ms0uG>~U;i$^*dC6Wk!=Ex{o0RC39TC9zad%Z*apFj< z9AweyYz9tt313U@B|T!#O0t9{M$sYy>d*y>=bIPsnnujINOt#$9f$ksOvBCF+8yiVc`&MJaP zlE{V$S}&DM83oDv^dh&NPqq&x^JV;QwTNm@o{{*iu*| zkb`4?jwjHjnK7<9h|H@c-TR`*PACog=kuVwe$ln6W&zK^k! zpu2>2Dww$e>Wr_9A}5_|OEat~Ij7s4!a4}I79vU*o7_$(TS}f%R*O5ISJxk~RJZdW zNHQPr4aBBJN)IP~IJgnD%!_9LJ@?I~lzXR4Y!G!b9v;!@Z$Bj3BFgqBpII6(MY|yE zb{Hj-D9w3SwOJ7)*Wlhj6nLbxeqe5l;I0$}Je9kh;`v@GmfPyVN^$(qbQbtSg)aqi zvnDg}$7wMw76-OmHkk`Qb$NQ#wY-cI(k~I!Goi%!j~cQo%FELy>LzwbLw>F!Y(CD1 zp)e5|K0;ltB#KtjaO&-rF5-8K+XWZZZgui6m3o@xlBB1^Fj%UNhkJ8r=bb!$n5B(u zmZ{9?q^gg+MV^PM4sYFoI6F~RvWM1&mP>q;+(G+!DH5&Wkn`&1uz>-k<|1P+N=J<& zG!bc;R@BYf7SM+zgK(coH_qL-Qf4F`wTEZM0mxYx6!$Wz1GNA?d{*9ji)>YH`Q|%_ z!kMdbyg2DOPeP}4q8h^V{ZsP9p8?C0toCFXe`=E^Jb5Of3%_U)(E9a`Q?;Ewh3UtHzWG8Ughxy464*r6Nk>GI-Hzcj9i_G2 z1;Y|c;Okf?M;Z18v>+Z#p4V7aSWyo=m&c9wUvsMU@hMLYO}W9Bkgo-f7UL)ZYrI>i z^*z3sm;!JPlBRf%sACMbj;WBU&*V-UiFZfNUWtqMN5;Id%)JGZ%r=Urm~XF^0l8z9 zg77g>j2;JPk7XgRpW@OlcI5O%QWNG0z)2C#n1#5PZzsBmUg#yYTh$Q4J&cC~u_#iJsJ|=!*4{p6c+9?loxVM;_SJ&YjIO@d#eJkcM@MBJ?&H!p$4ehX ziHu6Tv=A3am(b|EY%;CXFvFIdu{GdG+F2=iV%mX47Jw}6Ew-8bj$WOgo%F=4yW1+! zkn=ntNC$w&AP=K4@XhAYwrToCJA*4pmSw__YX$`w9T_j3$e*9~UeSc&u7mFDS&^U@ z{9SBWmfA9HV}DN-iA`|t4smA%@4tjE47zu#NXQCiR0p{9HwP8s9WGB5Hwg3jsu>aS z86o=dD+{TO9D3#HuxWqSrsV0gj)E92rmdB?2q(2r)4!{~(&TWCrSp@M`S}{Gd5`^A zje<-UBvj4(vOX_y9-yhJy*>+y@n^o|PUzB&jBa$K;~|)uPR@dq)_?o0;j8ARXng7$ zlQBRdM_?=9-+PpkL<>yAa0{po9dw`T&SdCuEj|^2w`prQ`{G6Ni|13alZ~Al`h{)@ z&pg1u)pIn@2&j+{M+B?<1~;G+OxVc*#9fi@e9{o>4Hn9l588&s^vUH*A^8P|6fn8; zpVo)d`Lzq`ZLBd`Q#^`l9UV+`F7sG7Aa1S!Odqr0-pb~J{TUl`^ZJt#JL_X|d^e5LU?8);L@PVSD@M7mgW zli#*54y+Eb8!S3X_zj-MZ~Y?BAw*iGvS_L&Rw+1qEv7#*tmbY`icAt_-}G+wUq-nB zVfNd^t&!`_I$X1Mx&JeF6l@>IPS@1iX7%_ZiKfp1d*KU+hJCBR(h~U@TRlD4h-Yd7 z{lFR<@CQ3F5d~G!i3Itg#Uo-#aqzs6w|ePIXmr7Kj>AmFh?)i>cW?7?P%)^ zs%giF9gmAHwZmnU@2UphMng!DjqDyGcB#L*J>=kRw)|blHMfZeo4mG$QOsJJxHqeMB2YeHE*E2|Fsi>gX7eM>s63O0x ztIkWK0{FEt&Ed0CwN_^?&7D4c&b)sYFyg2riFm@!#RJBXGX8zYH`P_f?O~3{cLx<+ z3(7+DHwg&{&#Q{ZzN}peS;~+DIuZ5g0`i%^w7Q8oub3-6B^yrDNk1_9W3_Yyr2J}T zR6iR(86E+*MWTg}uivfVw$90PD%k0;fl=#Vqca{4m<0 zi8xwGUZA&i{qsmzVf#g7BFR$Pv-t*x&v0dHZhSfepF!XyXj=zGh!KTuz$?>wrTnc* zF?ivwgQ|Q#HxorYD}_%**A%jiOLY4Xj8!EKbikyeZq&J;tHRLBVVdf?06xubV(7@V z(oach3?s{5!*mr7;yL_IhUL~jNh^I7NSw^q`FT-3O><3i4qJ1J*9Urh98>A;_REtk zAzk9}2N3f($E~eID~Wg&4{0|%U>&j+z4*~m)A1&hu1O3!@MZI;YMCE8x5l|XXVKl! z(F{Vj?(2q`5jKvJ|K}%YE-{YAr(L|_NJ_7Eu$+-O?^8ZeNg;4N8Q{tQG88=e0kD2q z)9(ym^fx1P_t0u%h4fA$vP9>?;g*h^=EzBF!O@{QP)u`iwf~tnmctM$rjJh7hJ#A2 zmoCyYq*NIHJf;a{-Bf|4Qo;Cs^2WOszO6P}7Y#IOC+#{cQ*%qkK%;u=+Cr#=0BrEr zzF)VE5fx)l3gtpXN{iEQma@NuDZzy#qg`T`cx0XoK(lGF%}pb6llvYtXi;K%%M^G2 zWg$m#R#;Bp$@s1H<85Cg+B&kQTM)pwA|I|>x$KcoSvU|#Jp5{7C2ebiSec}2@PP$g za1>gm6^LcQQ7a24B3>PBcrrY++3;DLUK=gsO0l8Sn(aTeeLcVyB%oN;k{IprNw^DW z!Q!FnQeKdDh=ZIn{1_OGlgtFd+)k=Ur+-r*8-`(}_2&YGvCZDemh+dHd1BLw&PPpA zr74J`OY0a`XQ4&H3k3T%1HQZ2WJs-ST{5quwDNK($)mbgT1UEpM%Q(=T5%7jpCTku z#*NwZIq20q?V|x>g0{hU8p1B^dw1+koiMvT>&nIRa@1t3W#HQ?;77dsTL`AXe+q0R z@aw9}(6GcdnuugwGkQ@_&v|oa|2CvqYxFI-<{6|rHQ zFkv|bR{?wV`@5m6Mt60{miFiE@V-E1Hz2KV7!YW1KTgq4`8j>id*#t$k5)Hug+>Y9 z+))AS!%r3o<-;RrOS30bGme32YtkP?*aD2kS4zX3$cHjpeYMIaphoqZn#0T@n#0;U z^Xy@~%Ax`S?uEM8`i3)^-+H2XI?tq`F9-;XmbvrhhZaizLm?Fy$`6(BMNeu>4C4DDzzn;;YT|m z2Hq&T7_H7e);#N6v@`;Ll8pEO_XX$x00000000000000000000000000000000000 z00000Bn#*2Rg$+TtK@`x;;)J5;H~MhrS}e86qTGq1WEav1QiR}pD^H|a^i%Ok)yNB zc10X~vmUK^9?q28a`2s*8mA~L7j_Mwjcax$g&!rb zlwD{)rW-GRwtxj)j;%ZQquCq6-C9g$(600009DP@(fWH}`0G6f7c ziq)ZJmNaXZbJsS?{6HDU#S8ChhUGHnOlJ~&_2d5r)}X_t*y{{97r9;4&+ zqHCKAX)9X~;UGu6yba=(Z_3x+5&29hRvZJu#xKY0Sz4EFWAA7)dK@5$;d%wN4Y&Zb zpAv}oA)LHt2f-Ed?sswmiEBLQ^bzH=Ohl9K)435`tn*&I_r)!M zgXuO;6cR*syzHT`H|yPaS;S26Qni9JGt(aRsCU-^uCRX$c^`0Qd|q;1kc%Vjj=8ip zt2G-{q)^M?Abn-8u7g+XY&r9fPy&9UoPK%GTPgfEB|uhQ>m)hJ8T{1W+S%$Gb23fp ztVgGG+puK&&%x!V9{rJx1zXc?o(GO?BfA7ohnJ?PX5%?a0^^FjI$Psj|6iOQn}!Da zW}nsFoou9g|GX+DNN-cG4CsY9g!norZ~4M52F*~H0M!jnwb{VW^axwSA^K~*E1GDx z=~`5ptHd^9M_`6W_L7naIq*_YW6Z`KODAKPAvu0Ie2S1oqx8{54%$h+6k!Dk4+sM& zeA@fKTRsM(EHgCJQt^6=KZ*Yb*_QM0Q}rEk(|v_gM=HOC@t^%n0H;GWU7}A+HF3z@ z7219u#(DFw?5+uVn=T_K8yJfUAi9@??#O~=e;>E^!hj9P6?xgAlYLGPw}sgreWoQ% zdC7gjzBY!**xZh3f>ahGh9qqdx~EYCuVO%mU9){smcS6%JnGq$PAu(i$ex|A!~m1o z*W1IG!9?^b1yu2xMDZC}m65jGBtl7v+#YA2BVLT_Fw9OK>#(F364!sTKQG>2uw zqHU3(YyoXWbrnqP5cFm!zWzsV-|Guw!2v19vxsx?Tm7Z4oIVa)D(&f?!2g4v998}S z_>LUQ6xL_%5?Hy8@)c<1!FE+tVG^u$8YHJO4r7C~ARLm&Pq6*%oSy$miIE?>r@Gb^N# z>Tk6H#|%!jQ}G$bf&K#0Tc(Y^FD8dpuZ(HVeETo9Ih2yt&4YJ8f^#Rbdjx89);Tll|JxisLe}!&Wg39U z5n%-7NI(`=2lXrmw3PXM+BBuP7&E?W{|>(?5qU^s_FpJwA=VYF0WT#yD2NtVcr z)VTjm&=>R+js4z+tU(4$xhlce;aMCOYfAO~L8VROl0RY%+#hNj?^1!#{^W$;@X5=4gbK^!d{V0P}0u z^^F5*rkQxhygxei9d3TD&f+~n_nrJd%&Y-!#yKF^kmzz}AY~Am?1+EysNOWA_}iy^ zmu5wW1qh+g5-#NpV+la4I*T=OL(5q|CmYMMCa3EH5lOT3Vlln(Qm<%z?tf0A5%zp9 z@vyPKYu-jfP7F!{p|ERJx+@c}FFc?|pA*-HI;slUwoo8etq0&G%HRi$#C?2mJofFO z;$i~hQCf0r*njMwjn_$qs8R#LdzLaiwS&%Il5w7Ilw;~TE)j*R1wQ=vKW&VYc}34_ zN*~2R@gUwm(~&bfw#$btYrK_-=0IVVjH??2*$BCKE{fNkV3j^KL$Sp!nAW{( zD$k9bc%=Yg>@m>)fyaxelY*{N(>r^Y;w#Z%f$40o0rqGO2iaVxt%-%s;My)2k!Yl5 zB5?L}u4xt68~o}{7>YYUVqz(=^X%WGks`iHRx?Vfm5VIvuk1gkceINCy{7Hjsr!h(R4}3}u93z_^$sr0|jysg0 z^G!eXjM(Ful*0XIQ{WH!U*ofK05n4=gZo~IG(vx0J@mDu;xOPr4^aVIB+%!oc3G;a z41HY9maSEBqJMEZ6P4W4qiJe6!n~`452|{fA>12C8@iVOd%Q6u#=4zUV$#^0Gh#rpc)WUEls0&B&p7bZTvJ3aW=t+gzi%y524!d>V~GyRJU-iq^r z>O`=T2lvg8y0NCq5>qaIzlWM@Hk}XB!(z7XE`mb*glz@NjwS}dj6DxTNu-m(kHzpdCRiE5HqifZ$1eGz&rA;+9#)F4#XbQe|rhU!nzmqtLF$OP} z?kgJu!kcUCU7*0vg|73%>^Z!I&T0!ZR#aTl=b|_Z+95#};j7csy$!L&h^Y*4s%rkF zMqPJkb#U_c^whn&%K`%1Jd0)>+oYW8s0QJ=L>W<>sJXd6ge_O{HvzeX0n!}L6TX4- z&)*F;!lk)vsr;+wRbqya!LcyNP-$@|X7ThqquV;$H*MZJCziVn_Qm z%N#x5y>@{<^i_s@Ohq>+4y)k*a+4~jqWHz?6}eJ&B!8;t1Q`JRJd!J5X`c%mPx^Zk zHBw!#0eSRzhB_XOyX4*hhuvA=D|rZ({@P1$$F-~K?sef5+bqjNQ&=ZJa_H3*z3$d& zrPLTA@2>lWWI$eE}gPOgR4CicuN(&Ml>1wvPGE#UN_2zyP1jgc}I^-^x-?|)OK_^eRYfhsRl??cZ?TN!Xz#(pjWFZH< zgV`C`01lEltATw~AM8mq}GZ-^M zj5X0Dp(N+;rgCzi;FH1TB4}{x$v%<^(K~$%u3V^9WR8B=L}^d#@stb=$e~4+MY7uA z%?W5m*6Pd;K)~^v-MYuO4a}`@D{rj;H<(yM212O*y)RK(Xd=@)M#H zFPS;-P@zGm5FMMkwaambKz_Z>EO|pDyBCA7Kx|h6!oBKDCN-j{InvkW-EBB(&-S)W){M&MD9zZLBg zuu1j&p9nRr99vcjAgPl)IS-1w6*Rju9O^w?-^(6SoPxlh)&wlkqv<^0BH_MRF)Xtu z6V?Gm3;uMZ(+B3BQ`&u2)vn)19JO}Cd0)b6|eXHrNc5*5#5M)!*!d8Y_qF4A9oe)3?v z;LpN;a5~NTOb2H((0x)cDwxPSX=NI&N%sP>IzavUf?o}f&Qn=|0(-3_0+6>QXwd*b{q40~&eX`CcMGZ;XvbqQk&+0KNxt370-G{e^Ss77 zc~hdpsLpQYkUAAHur??sqeXNGP_|Dki@(yM^+>wsfGjwNd|{-Ld$Cgx@nq(u>$!Z> zLv@iOsCLf$YsLG35{D%=nAqjZm9`V^@t%lk*`ziB}g4*Ib=(Z z=Gno;M`R_P@zESv>Y!yvpq8|v+iwnn?m;r4WS|*cr}3|$X=olr8l@Y7v+%&$Tm-;T zk19l*vH{`f1^T@ps?gBz8LMDIM%jzbT>4>_AJSfPt4Nim}p37m#A~ zPIAR4j&_Krhg9#UcyySSIvU`&#@#OUcr}L~c+P|;6Y^*CVB*TVnl*iY40c~otWNSS z#XGT;LhRs0g?L5TeJ({#To)xDigbveLDBo7hYJX*AoNKkHxgU#D-)^^sA=WDx5^^( zgPIdUO+EeLxDuF2%v$U(8m#Q5dYsYffIJi|uY(pgU>Mx^stNA!8$0Vq=)u#NsDYUa zkNqU$Nj`BpRg2cUnMSyP);F3dk@IfENn)ObTKLlgT4*p^Pyo~0HyqjPRFPLjjfIUp zdf3}~>76%jmxCsG*PKP~*0KdqiKB)h3hilp9v-g-royeTz@UHyqW998F-;)wE8X@R z(+!G%RceTsZggWC)I&&Jn(ds{N(IrPCB3LDq#n}W^G<<8LXM|O5a_-e(?+NAEm87+ zcjS&7yexZ!^5a;5W5!-MBzH0k0+_q;KgdC8Sd3>?*OW-1EM^Ih?UpRCdleI8!SW)d zOwsFN_R5aAWUAxt#WGZ(gt_!JE|$jRc<`l{=4dqQHI%lkFukwbkifCG=q z|BBn{Imrr%f2JL2MH#lW5pUu@9v)l&i%vf0XYS#i>YO!YyIqY7GpD&nKtW7b0)Vx| z79YSTswu^<_RL0!A5`0d%j7^+moEeO09ReX;gBO_E%+?D=Wc><5A=Unq*iMMmYYXJd|D6TNOqy}}Y8D+7llOJrlkJ0A_3pvXsS(f_ zYFvy&bF^@Vo+uG|t-5)$Gt~g!2{~z0F|L^|JU1eMEhRKQ?b*Qf+emLOvirok)DRrY z_#@429}C@3t1)F!@z?O~;P4lxz%dpEI|ZS|iG24Q(AtX{7yHMGB_vwDn@h3C^!prH zCXMTqD6~=?R$G=d6*P>05yx;Z=U%}xx0Wto87a$YJVJyM_}ZuCY6MtWL$z6-we$DehK(o)_ZU(uhQe0ccrI53`vfZcrXfkZ8*V;X16Z&9_&faVKNZKR5!*`=W*5{b!^ z%c?Bf9}Up2(%&@{^Q@nh3&&)dq%Z>2 zJ3WUx=lwG60Uc-5NNE%OtS!K|etV6IfxED#Uad1F`pQOWAqB>!bNYKOj+yy_lJ(m% zSV}^~VVyi6ZnHRA54cuO+6MmB8 z4W|{}_`w7tv4cOJoB;-9mEn?i(9RyFv_41MAbG(1@{U?oJIomzEinHnVt>7byqEf? z5J4&08CSyzAh(BLaZ3>@k9!E&5e3qK^V__iwJnJ8*!)<|g7{(63Jd`a{CmR`Fs4 z*DDJqGsDI&1`IU|zC($ApIdBGb$L0qiOnc#e@4EcmOl7e(YM*}gA8kFtO4y16Xqht z9a893XYZ>D=;(SyYM1mG_zYpwJpI-!b?1+Dw^V)%Tk``aJN|)yMD)*2cNLjX!M(ebDBS7xTFe+@onr&r)h-aDx za8oI~_}Fn*m=X44CP&pVe7_w_woSO%+LSn!t4xxYu?SF+W~>o`&tKE&Vco79V{fPLeyQtw@4isO;f_F``u7wJXyzkpm6iIEs4bw^0w z&=e`;U!3e)I2jMnwIh&8s!Ww)C@>EJ5aa+^WZ{#~knFXj=#C{zJ$5a&bcIWU{Sh+9 zvKZGE|Eh+_sAMn}^3_Wv1SZ-foc-yBxcL%*D)3$lJ~n}>nFSGu9#>@-7=*upRNCpF z+eZ!K{_;5P^H2Z*hhu9w`!^h$?>#-&nc>nFB~H*}RprtAw;ool>*Bo3XYIGKE~oAM zVPPvx{GMgefC99bRP*+3IXB*Vd$;g{hT0@6qg;H6T|Sizu=7zV-Yz)8`|I|5feCA+ zAOMO&RppH)3AV1&e%^hmqDYqp7bybmqMS$;xV9$BTE0bjkla5VL!DmaE{#d6$+ZiA z4dld3F!74fe2Yj0w5?zIWe@-PnJT~-9b-+}ut4C$xgY=l0a_)MjQ|=wX^8?wwhDsj nYCPU_ffKeAJ+6>4vUv9WlDbT+u8QoJdnq;m0000000000VUGFS literal 0 HcmV?d00001 diff --git a/website/versioned_docs/version-v2.7.0/community/showcase/tinyrdm.mdx b/website/versioned_docs/version-v2.7.0/community/showcase/tinyrdm.mdx index cd9cec8b309..e3124bab727 100644 --- a/website/versioned_docs/version-v2.7.0/community/showcase/tinyrdm.mdx +++ b/website/versioned_docs/version-v2.7.0/community/showcase/tinyrdm.mdx @@ -2,7 +2,8 @@ ```mdx-code-block

- + +

``` From ae4cb4e86113fd2c821444dbb269ef38b4cd16b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 19:36:40 +1100 Subject: [PATCH 005/369] Bump tj-actions/changed-files from 35 to 41 in /.github/workflows (#3165) Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 35 to 41. - [Release notes](https://github.com/tj-actions/changed-files/releases) - [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/changed-files/compare/v35...v41) --- updated-dependencies: - dependency-name: tj-actions/changed-files dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/upload-source-documents.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upload-source-documents.yml b/.github/workflows/upload-source-documents.yml index c94245ba507..a581ed0a01e 100644 --- a/.github/workflows/upload-source-documents.yml +++ b/.github/workflows/upload-source-documents.yml @@ -15,7 +15,7 @@ jobs: - name: Verify Changed files id: changed-files - uses: tj-actions/changed-files@v35 + uses: tj-actions/changed-files@v41 with: files: | website/**/*.mdx From 56fb047d89a01b4c846f26377d5e26e06926eaa6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 19:37:41 +1100 Subject: [PATCH 006/369] Bump tj-actions/verify-changed-files in /.github/workflows (#3164) Bumps [tj-actions/verify-changed-files](https://github.com/tj-actions/verify-changed-files) from 11.1 to 17. - [Release notes](https://github.com/tj-actions/verify-changed-files/releases) - [Changelog](https://github.com/tj-actions/verify-changed-files/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/verify-changed-files/compare/v11.1...v17) --- updated-dependencies: - dependency-name: tj-actions/verify-changed-files dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 9bd98c17183..8435861eefd 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v3 - name: Verify Changed files - uses: tj-actions/verify-changed-files@v11.1 + uses: tj-actions/verify-changed-files@v17 id: verify-changed-files with: files: | From b083d1d41c71a15e9e47a1baab0889cdae4e54cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 19:38:06 +1100 Subject: [PATCH 007/369] Bump github.com/go-git/go-git/v5 from 5.3.0 to 5.11.0 in /v2 (#3161) Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.3.0 to 5.11.0. - [Release notes](https://github.com/go-git/go-git/releases) - [Commits](https://github.com/go-git/go-git/compare/v5.3.0...v5.11.0) --- updated-dependencies: - dependency-name: github.com/go-git/go-git/v5 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- v2/go.mod | 29 +++++++------ v2/go.sum | 125 ++++++++++++++++++++++++++---------------------------- 2 files changed, 77 insertions(+), 77 deletions(-) diff --git a/v2/go.mod b/v2/go.mod index 0d04fd4114d..963a352f7fa 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -10,7 +10,7 @@ require ( github.com/charmbracelet/glamour v0.5.0 github.com/flytam/filenamify v1.0.0 github.com/fsnotify/fsnotify v1.4.9 - github.com/go-git/go-git/v5 v5.3.0 + github.com/go-git/go-git/v5 v5.11.0 github.com/go-ole/go-ole v1.2.6 github.com/godbus/dbus/v5 v5.1.0 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 @@ -32,7 +32,7 @@ require ( github.com/pterm/pterm v0.12.49 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 github.com/samber/lo v1.38.1 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.8.4 github.com/tc-hib/winres v0.2.1 github.com/tidwall/sjson v1.1.7 github.com/tkrajina/go-reflector v0.5.6 @@ -40,34 +40,37 @@ require ( github.com/wailsapp/mimetype v1.4.1 github.com/wzshiming/ctc v1.2.3 golang.org/x/mod v0.12.0 - golang.org/x/net v0.17.0 + golang.org/x/net v0.19.0 golang.org/x/sys v0.15.0 - golang.org/x/tools v0.6.0 + golang.org/x/tools v0.13.0 ) require ( atomicgo.dev/cursor v0.1.1 // indirect atomicgo.dev/keyboard v0.2.8 // indirect bitbucket.org/creachadair/shell v0.0.7 // indirect - github.com/Microsoft/go-winio v0.4.16 // indirect + dario.cat/mergo v1.0.0 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/alecthomas/chroma v0.10.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect + github.com/cloudflare/circl v1.3.3 // indirect github.com/containerd/console v1.0.3 // indirect + github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dlclark/regexp2 v1.4.0 // indirect - github.com/emirpasic/gods v1.12.0 // indirect + github.com/emirpasic/gods v1.18.1 // indirect github.com/ghodss/yaml v1.0.0 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.2.0 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/gookit/color v1.5.2 // indirect github.com/gorilla/css v1.0.0 // indirect - github.com/imdario/mergo v0.3.12 // indirect github.com/jaypipes/pcidb v1.0.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect - github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect - github.com/kr/pretty v0.3.0 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/lithammer/fuzzysearch v1.1.5 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -79,16 +82,18 @@ require ( github.com/muesli/termenv v0.9.0 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/sergi/go-diff v1.2.0 // indirect + github.com/skeema/knownhosts v1.2.1 // indirect github.com/tidwall/gjson v1.9.3 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae // indirect - github.com/xanzy/ssh-agent v0.3.0 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/yuin/goldmark v1.4.13 // indirect github.com/yuin/goldmark-emoji v1.0.1 // indirect diff --git a/v2/go.sum b/v2/go.sum index f6d59f7ce96..f7687932e77 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -4,6 +4,8 @@ atomicgo.dev/keyboard v0.2.8 h1:Di09BitwZgdTV1hPyX/b9Cqxi8HVuJQwWivnZUEqlj4= atomicgo.dev/keyboard v0.2.8/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= bitbucket.org/creachadair/shell v0.0.7 h1:Z96pB6DkSb7F3Y3BBnJeOZH2gazyMTWlvecSD4vDqfk= bitbucket.org/creachadair/shell v0.0.7/go.mod h1:oqtXSSvSYr4624lnnabXHaBsYW6RD80caLi2b3hJk0U= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= @@ -14,21 +16,19 @@ github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYew github.com/MarvinJWendt/testza v0.4.3 h1:u2XaM4IqGp9dsdUmML8/Z791fu4yjQYzOiufOtJwTII= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= @@ -36,46 +36,47 @@ github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= github.com/bitfield/script v0.19.0 h1:W24f+FQuPab9gXcW8bhcbo5qO8AtrXyu3XOnR4zhHN0= github.com/bitfield/script v0.19.0/go.mod h1:ana6F8YOSZ3ImT8SauIzuYSqXgFVkSUJ6kgja+WMmIY= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/charmbracelet/glamour v0.5.0 h1:wu15ykPdB7X6chxugG/NNfDUbyyrCLV9XBalj5wdu3g= github.com/charmbracelet/glamour v0.5.0/go.mod h1:9ZRtG19AUIzcTm7FGLGbq3D5WKQ5UyZBbQsMQN0XIqc= +github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/flytam/filenamify v1.0.0 h1:ewx6BY2dj7U6h2zGPJmt33q/BjkSf/YsY/woQvnUNIs= github.com/flytam/filenamify v1.0.0/go.mod h1:Dzf9kVycwcsBlr2ATg6uxjqiFgKGH+5SKFuhdeP5zu8= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.2.0 h1:GcoouCP9J+5slw2uXAocL70z8ml4A8B/H8nEPt6CLPk= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= -github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= -github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc= -github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw= +github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= +github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -86,8 +87,6 @@ github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI= github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/jackmordaunt/icns v1.0.0 h1:RYSxplerf/l/DUd09AHtITwckkv/mqjVv4DjYdPmAMQ= github.com/jackmordaunt/icns v1.0.0/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo= github.com/jaypipes/ghw v0.12.0 h1:xU2/MDJfWmBhJnujHY9qwXQLs3DBsf0/Xa9vECY0Tho= @@ -99,22 +98,17 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M= github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= @@ -163,12 +157,13 @@ github.com/muesli/termenv v0.9.0 h1:wnbOaGz+LUR3jNT0zOzinPnyDaCZUQRZj9GxK8eRVl8= github.com/muesli/termenv v0.9.0/go.mod h1:R/LzAKf+suGs4IsO95y7+7DpFHO0KABgnZqtlyx2mBw= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -186,28 +181,26 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI= github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA= github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk= github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= @@ -236,8 +229,8 @@ github.com/wzshiming/ctc v1.2.3 h1:q+hW3IQNsjIlOFBTGZZZeIXTElFM4grF4spW/errh/c= github.com/wzshiming/ctc v1.2.3/go.mod h1:2tVAtIY7SUyraSk0JxvwmONNPFL4ARavPuEsg5+KA28= github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae h1:tpXvBXC3hpQBDCc9OojJZCQMVRAbT3TTdUMP8WguXkY= github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae/go.mod h1:VTAq37rkGeV+WOybvZwjXiJOicICdpLCN8ifpISjK20= -github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= -github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -246,10 +239,11 @@ github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os= github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= @@ -263,30 +257,28 @@ golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -297,8 +289,11 @@ golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= @@ -307,38 +302,38 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From f1265c527e72284b4c85a3f082e339e64f5a5066 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 19:43:00 +1100 Subject: [PATCH 008/369] chore: update sponsors.svg (#3150) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 38 +++++++++++++++------------------ 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index ceb2bbcf8ee..3f4202f3c43 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -105,29 +105,29 @@ text {
+ + + + - + - - - + + - - + + + - + - -Helpers - - - - + +Helpers @@ -151,24 +151,20 @@ text { - - - - - + - + - + - + From f7c19469a71d6c5c8ad2d767ac23bc3e05290230 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Thu, 4 Jan 2024 02:26:24 +0800 Subject: [PATCH 009/369] v2 [#3133] SingleInstanceData: Fill missing WD as is (#3154) * [#3133] SingleInstanceData: Fill missing WD as is * Apply suggestions from code review Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Fix: missing `import` for AI suggestions * Add changelog entry --------- Co-authored-by: Lea Anthony Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../frontend/desktop/linux/single_instance.go | 8 ++++++++ .../frontend/desktop/windows/single_instance.go | 12 +++++++++++- website/src/pages/changelog.mdx | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/v2/internal/frontend/desktop/linux/single_instance.go b/v2/internal/frontend/desktop/linux/single_instance.go index 9d6426e141a..0317dee4912 100644 --- a/v2/internal/frontend/desktop/linux/single_instance.go +++ b/v2/internal/frontend/desktop/linux/single_instance.go @@ -7,6 +7,7 @@ import ( "encoding/json" "github.com/godbus/dbus/v5" "github.com/wailsapp/wails/v2/pkg/options" + "log" "os" "strings" ) @@ -55,8 +56,15 @@ func SetupSingleInstance(uniqueID string) { data := options.SecondInstanceData{ Args: os.Args[1:], } + data.WorkingDirectory, err = os.Getwd() + if err != nil { + log.Printf("Failed to get working directory: %v", err) + return + } + serialized, err := json.Marshal(data) if err != nil { + log.Printf("Failed to marshal data: %v", err) return } diff --git a/v2/internal/frontend/desktop/windows/single_instance.go b/v2/internal/frontend/desktop/windows/single_instance.go index 222d9fe1a99..a02b7edb926 100644 --- a/v2/internal/frontend/desktop/windows/single_instance.go +++ b/v2/internal/frontend/desktop/windows/single_instance.go @@ -7,6 +7,7 @@ import ( "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" "github.com/wailsapp/wails/v2/pkg/options" "golang.org/x/sys/windows" + "log" "os" "syscall" "unsafe" @@ -51,7 +52,16 @@ func SetupSingleInstance(uniqueId string) { data := options.SecondInstanceData{ Args: os.Args[1:], } - serialized, _ := json.Marshal(data) + data.WorkingDirectory, err = os.Getwd() + if err != nil { + log.Printf("Failed to get working directory: %v", err) + return + } + serialized, err := json.Marshal(data) + if err != nil { + log.Printf("Failed to marshal data: %v", err) + return + } SendMessage(hwnd, string(serialized)) // exit second instance of app after sending message diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index f22628551dd..8f28a93c5be 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Docs for IsZoomControlEnabled and ZoomFactor. Fixed by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/3137) - Fixed `-compiler` flag for `wails build`, `wails dev` and `wails generate module`. Fixed in [PR](https://github.com/wailsapp/wails/pull/3121) by [@xtrafrancyz](https://github.com/xtrafrancyz) +- Fixed uninitialized `SecondInstanceData.WorkingDirectory` on linux and windows ([#3154](https://github.com/wailsapp/wails/pull/3154)). ## v2.7.1 - 2023-12-10 From bf389e3914c1b1a8f1ad32a32e0679aa08d61649 Mon Sep 17 00:00:00 2001 From: ALMAS <9382335+almas1992@users.noreply.github.com> Date: Mon, 8 Jan 2024 05:08:04 +0800 Subject: [PATCH 010/369] [v2/Mac] Handle application terminate (#3157) * [v2/Mac] Handle application terminate * add change log --------- Co-authored-by: Lea Anthony --- v2/internal/frontend/desktop/darwin/AppDelegate.m | 6 ++++++ website/src/pages/changelog.mdx | 1 + 2 files changed, 7 insertions(+) diff --git a/v2/internal/frontend/desktop/darwin/AppDelegate.m b/v2/internal/frontend/desktop/darwin/AppDelegate.m index 18ecfbcff63..318c333d861 100644 --- a/v2/internal/frontend/desktop/darwin/AppDelegate.m +++ b/v2/internal/frontend/desktop/darwin/AppDelegate.m @@ -9,6 +9,7 @@ #import #import "AppDelegate.h" +#import "message.h" @implementation AppDelegate -(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename @@ -22,6 +23,11 @@ - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender return NO; } +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { + processMessage("Q"); + return NSTerminateCancel; +} + - (void)applicationWillFinishLaunching:(NSNotification *)aNotification { [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; if (self.alwaysOnTop) { diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index 8f28a93c5be..7f409ca275d 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add Apple Silicon hardware detection to `wails doctor`. Changed by @almas1992 in [PR](https://github.com/wailsapp/wails/pull/3129) - Remove quarantine attribute on macOS binaries. Changed by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/3118) - Added documentation for a common GStreamer error on Linux systems. Changed by [@mkwsnyder](https://github.com/mkwsnyder) in [PR](https://github.com/wailsapp/wails/pull/3134) +- Add dock icon right-click exit handling by @almas1992 in [PR](https://github.com/wailsapp/wails/pull/3157) ### Fixed - Docs for IsZoomControlEnabled and ZoomFactor. Fixed by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/3137) From cf2d16c1fddec213b017eb8ad1e82d053129c3a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jan 2024 06:14:31 +1100 Subject: [PATCH 011/369] Bump github.com/cloudflare/circl from 1.3.3 to 1.3.7 in /v2 (#3185) Bumps [github.com/cloudflare/circl](https://github.com/cloudflare/circl) from 1.3.3 to 1.3.7. - [Release notes](https://github.com/cloudflare/circl/releases) - [Commits](https://github.com/cloudflare/circl/compare/v1.3.3...v1.3.7) --- updated-dependencies: - dependency-name: github.com/cloudflare/circl dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- v2/go.mod | 2 +- v2/go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/v2/go.mod b/v2/go.mod index 963a352f7fa..a38dd1a2282 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -55,7 +55,7 @@ require ( github.com/StackExchange/wmi v1.2.1 // indirect github.com/alecthomas/chroma v0.10.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect - github.com/cloudflare/circl v1.3.3 // indirect + github.com/cloudflare/circl v1.3.7 // indirect github.com/containerd/console v1.0.3 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/v2/go.sum b/v2/go.sum index f7687932e77..b9b7eb62073 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -39,8 +39,9 @@ github.com/bitfield/script v0.19.0/go.mod h1:ana6F8YOSZ3ImT8SauIzuYSqXgFVkSUJ6kg github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/charmbracelet/glamour v0.5.0 h1:wu15ykPdB7X6chxugG/NNfDUbyyrCLV9XBalj5wdu3g= github.com/charmbracelet/glamour v0.5.0/go.mod h1:9ZRtG19AUIzcTm7FGLGbq3D5WKQ5UyZBbQsMQN0XIqc= -github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= From 12d633642115f077a67dac5a65180581062eb5e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jan 2024 23:32:36 +1100 Subject: [PATCH 012/369] Bump follow-redirects from 1.15.2 to 1.15.4 in /website (#3188) Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.2 to 1.15.4. - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.2...v1.15.4) --- updated-dependencies: - dependency-name: follow-redirects dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- website/pnpm-lock.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index 44e36e6568d..51792e1c4d9 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -3573,7 +3573,7 @@ packages: /axios@0.21.3: resolution: {integrity: sha512-JtoZ3Ndke/+Iwt5n+BgSli/3idTvpt5OjKyoCmz4LX5+lPiY5l7C1colYezhlxThjNa/NhngCUWZSZFypIFuaA==} dependencies: - follow-redirects: 1.15.2 + follow-redirects: 1.15.4 transitivePeerDependencies: - debug dev: false @@ -3581,7 +3581,7 @@ packages: /axios@0.25.0: resolution: {integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==} dependencies: - follow-redirects: 1.15.2 + follow-redirects: 1.15.4 transitivePeerDependencies: - debug dev: false @@ -5048,8 +5048,8 @@ packages: - encoding dev: false - /follow-redirects@1.15.2: - resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} + /follow-redirects@1.15.4: + resolution: {integrity: sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -5550,7 +5550,7 @@ packages: engines: {node: '>=8.0.0'} dependencies: eventemitter3: 4.0.7 - follow-redirects: 1.15.2 + follow-redirects: 1.15.4 requires-port: 1.0.0 transitivePeerDependencies: - debug From 9ccb17bfd053084a78e9da7c29eaad3407b6b67b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 08:27:49 +1100 Subject: [PATCH 013/369] chore: update sponsors.svg (#3204) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index 3f4202f3c43..b4e54631865 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -129,42 +129,46 @@ text { Helpers - + - + - + - + - + - + - + - + - + - + + + + + From 3e5df3c7f1a1c9939522afdea6d94e4e8e34a770 Mon Sep 17 00:00:00 2001 From: ALMAS Date: Wed, 17 Jan 2024 19:35:15 +0800 Subject: [PATCH 014/369] [v2/Windows]Set default extension for save file dialog (#3205) * Set default extension for save file dialog * add change log --------- Co-authored-by: Lea Anthony --- v2/internal/frontend/desktop/windows/dialog.go | 4 ++++ website/src/pages/changelog.mdx | 1 + 2 files changed, 5 insertions(+) diff --git a/v2/internal/frontend/desktop/windows/dialog.go b/v2/internal/frontend/desktop/windows/dialog.go index 7aca4289438..573325886a1 100644 --- a/v2/internal/frontend/desktop/windows/dialog.go +++ b/v2/internal/frontend/desktop/windows/dialog.go @@ -121,6 +121,10 @@ func (f *Frontend) SaveFileDialog(options frontend.SaveDialogOptions) (string, e Folder: defaultFolder, } + if len(options.Filters) > 0 { + config.DefaultExtension = strings.TrimPrefix(strings.Split(options.Filters[0].Pattern, ";")[0], "*") + } + result, err := f.showCfdDialog( func() (cfd.Dialog, error) { return cfd.NewSaveFileDialog(config) diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index 7f409ca275d..c24d93e803d 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Docs for IsZoomControlEnabled and ZoomFactor. Fixed by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/3137) - Fixed `-compiler` flag for `wails build`, `wails dev` and `wails generate module`. Fixed in [PR](https://github.com/wailsapp/wails/pull/3121) by [@xtrafrancyz](https://github.com/xtrafrancyz) - Fixed uninitialized `SecondInstanceData.WorkingDirectory` on linux and windows ([#3154](https://github.com/wailsapp/wails/pull/3154)). +- Fixed save file dialog not appending file extension automatically on Windows by @almas1992 in [PR](https://github.com/wailsapp/wails/pull/3205) ## v2.7.1 - 2023-12-10 From b498cddcad18cb0c01af752f8004a062094acfd6 Mon Sep 17 00:00:00 2001 From: Luke Watts Date: Wed, 17 Jan 2024 11:37:58 +0000 Subject: [PATCH 015/369] Windows nsis install documentation improvements (#3179) * Adding additional NSIS install methods (Scoop, Winget) to windows-installer.mdx Adding Scoop and Winget package managers to the list of methods by which NSIS can be installed. * Update windows-installer.mdx Reordering so chocolatey is last, as Scoop or Winget are better/newer options --- website/docs/guides/windows-installer.mdx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/website/docs/guides/windows-installer.mdx b/website/docs/guides/windows-installer.mdx index 53373488660..c65dc6d3422 100644 --- a/website/docs/guides/windows-installer.mdx +++ b/website/docs/guides/windows-installer.mdx @@ -18,13 +18,26 @@ Wails supports generating Windows installers using the [NSIS installer](https:// The installer is available on the [NSIS Download](https://nsis.sourceforge.io/Download) page. +You can install with [Scoop](https://scoop.sh/) (which will automatically add it to your PATH): + +``` +scoop add bucket extras +scoop install nsis +``` + +Or, you can use Winget (on Windows 10+): + +``` +winget install NSIS.NSIS --silent +``` + If you use the chocolatey package manager, run the following script: ``` choco install nsis ``` -If you install NSIS manually, you need to add the _Bin_ folder, which contains `makensis.exe`, in your NSIS installation to your path. +**NOTE:** If you install NSIS manually, you need to add the _Bin_ folder, which contains `makensis.exe`, in your NSIS installation to your path. [Here](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/) is a good tutorial on how to add to path on Windows. ### Linux From f9aa4d3b602f56240ea07b19007f3126012f3ea1 Mon Sep 17 00:00:00 2001 From: Dana Woodman Date: Wed, 17 Jan 2024 03:40:12 -0800 Subject: [PATCH 016/369] Give explicity example of importing JS runtime (#3178) * Give explicity example of importing JS runtime No where in the docs, google, github issues or discussions could I find an example of importing the runtime JS but after some experimentation I figured it out. I think it would help future users if a simple example was shown like this so they have a clear reference of how to import the runtime. * make generic * Update changelog.mdx --------- Co-authored-by: Lea Anthony --- website/src/pages/changelog.mdx | 1 + .../version-v2.7.0/reference/runtime/intro.mdx | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index c24d93e803d..f8868d4290b 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add Apple Silicon hardware detection to `wails doctor`. Changed by @almas1992 in [PR](https://github.com/wailsapp/wails/pull/3129) - Remove quarantine attribute on macOS binaries. Changed by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/3118) - Added documentation for a common GStreamer error on Linux systems. Changed by [@mkwsnyder](https://github.com/mkwsnyder) in [PR](https://github.com/wailsapp/wails/pull/3134) +- Added documentation on explicity example of importing JS runtime. Changed by [@danawoodman](https://github.com/danawoodman) in [PR](https://github.com/wailsapp/wails/pull/3178) - Add dock icon right-click exit handling by @almas1992 in [PR](https://github.com/wailsapp/wails/pull/3157) ### Fixed diff --git a/website/versioned_docs/version-v2.7.0/reference/runtime/intro.mdx b/website/versioned_docs/version-v2.7.0/reference/runtime/intro.mdx index 3c491ecf046..9174e9f8007 100644 --- a/website/versioned_docs/version-v2.7.0/reference/runtime/intro.mdx +++ b/website/versioned_docs/version-v2.7.0/reference/runtime/intro.mdx @@ -34,6 +34,13 @@ The JavaScript library is available to the frontend via the `window.runtime` map mode that provides TypeScript declarations for the runtime. This should be located in the `wailsjs` directory in your frontend directory. +e.g. if you wanted to import the [EventsOn](./events/#eventson) function in your frontend, you can do the following: + +```ts +// src/index.js (for example) +import { EventsOn } from '../wailsjs/runtime' +``` + ### Hide Go: `Hide(ctx context.Context)`
From 3a230b563f9df8b957ac6ae913d19d3ea0d82499 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 19:49:09 +1100 Subject: [PATCH 017/369] chore: update sponsors.svg (#3210) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index b4e54631865..78b283b7ea9 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -113,20 +113,16 @@ text { - + - - + + - - - - - + - + Helpers From cec6551c5ea8d3a8f642a3842af6e2dfa6662761 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 21 Jan 2024 17:45:38 +1100 Subject: [PATCH 018/369] chore: update sponsors.svg (#3215) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index 78b283b7ea9..037686aebbf 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -125,46 +125,50 @@ text { Helpers - + - + - + - + - + - + - + - + - + - + - + + + + + From 55a7d317bd9e12b154d0c24021b0dd912c3faa8d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 21:04:20 +1100 Subject: [PATCH 019/369] chore: update sponsors.svg (#3217) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 54 ++++++++++++++------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index 037686aebbf..7ad5a6bd4b6 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -85,90 +85,82 @@ text { - - - - - + - + - + - + - + - + - - - - + - + - + + + + Helpers - + - + - + - - - - - + - + - + - + - + - + - + - + From ad7f7f76bc6364fad839e154368b9d8fa56bc831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20Sj=C3=B6kvist?= <35743604+williamsjokvist@users.noreply.github.com> Date: Fri, 26 Jan 2024 22:41:15 +0100 Subject: [PATCH 020/369] chore: add cfn-tracker to community docs (#3221) * chore: add cfn tracker to community docs * run format --- .../docs/community/showcase/cfntracker.mdx | 39 ++++++++++++++++ .../current/community/showcase/cfntracker.mdx | 42 ++++++++++++++++++ .../community/showcase/cfntracker.mdx | 42 ++++++++++++++++++ .../community/showcase/cfntracker.mdx | 42 ++++++++++++++++++ .../current/community/showcase/cfntracker.mdx | 39 ++++++++++++++++ .../community/showcase/cfntracker.mdx | 39 ++++++++++++++++ .../community/showcase/cfntracker.mdx | 39 ++++++++++++++++ .../current/community/showcase/cfntracker.mdx | 39 ++++++++++++++++ .../community/showcase/cfntracker.mdx | 39 ++++++++++++++++ .../community/showcase/cfntracker.mdx | 39 ++++++++++++++++ .../current/community/showcase/cfntracker.mdx | 41 +++++++++++++++++ .../community/showcase/cfntracker.mdx | 41 +++++++++++++++++ .../community/showcase/cfntracker.mdx | 41 +++++++++++++++++ .../current/community/showcase/cfntracker.mdx | 41 +++++++++++++++++ .../community/showcase/cfntracker.mdx | 41 +++++++++++++++++ .../community/showcase/cfntracker.mdx | 41 +++++++++++++++++ .../current/community/showcase/cfntracker.mdx | 39 ++++++++++++++++ .../current/community/showcase/cfntracker.mdx | 35 +++++++++++++++ .../community/showcase/cfntracker.mdx | 35 +++++++++++++++ .../community/showcase/cfntracker.mdx | 35 +++++++++++++++ website/static/img/showcase/cfntracker.webp | Bin 0 -> 93970 bytes .../community/showcase/cfntracker.mdx | 39 ++++++++++++++++ .../community/showcase/cfntracker.mdx | 39 ++++++++++++++++ 23 files changed, 867 insertions(+) create mode 100644 website/docs/community/showcase/cfntracker.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/vi/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx create mode 100644 website/static/img/showcase/cfntracker.webp create mode 100644 website/versioned_docs/version-v2.6.0/community/showcase/cfntracker.mdx create mode 100644 website/versioned_docs/version-v2.7.0/community/showcase/cfntracker.mdx diff --git a/website/docs/community/showcase/cfntracker.mdx b/website/docs/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..8fab23b75ad --- /dev/null +++ b/website/docs/community/showcase/cfntracker.mdx @@ -0,0 +1,39 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Track any Street +Fighter 6 or V CFN profile's live matches. Check +[the website](https://cfn.williamsjokvist.se/) to get started. + +## Features + +- Real-time match tracking +- Storing match logs and statistics +- Support for displaying live stats to OBS via Browser Source +- Support for both SF6 and SFV +- Ability for users to create their own OBS Browser themes with CSS + +### Major tech used alongside Wails + +- [Task](https://github.com/go-task/task) - wrapping the Wails CLI to make + common commands easy to use +- [React](https://github.com/facebook/react) - chosen for its rich ecosystem + (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - used for its fast dependency + resolution and build-time +- [Rod](https://github.com/go-rod/rod) - headless browser automation for + authentication and polling changes +- [SQLite](https://github.com/mattn/go-sqlite3) - used for storing matches, + sessions and profiles +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + a http stream to send tracking updates to OBS browser sources +- [i18next](https://github.com/i18next/) - with backend connector to serve + localization objects from the Go layer +- [xstate](https://github.com/statelyai/xstate) - state machines for auth + process and tracking diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..568c964b70e --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx @@ -0,0 +1,42 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Suivez les +matchs en direct de n'importe quel profil Street Fighter 6 ou V CFN. Consultez +[le site Web](https://cfn.williamsjokvist.se/) pour commencer. + +## Caractéristiques + +- Suivi des matchs en temps réel +- Stockage des journaux de match et des statistiques +- Prise en charge de l'affichage des statistiques en direct sur OBS via la + source du navigateur +- Prise en charge de SF6 et SFV +- Possibilité pour les utilisateurs de créer leurs propres thèmes de navigateur + OBS avec CSS + +### Technologie majeure utilisée aux côtés de Wails + +- [Tâche](https://github.com/go-task/task) - encapsulation de la CLI Wails pour + rendre les commandes courantes faciles à utiliser +- [React](https://github.com/facebook/react) - choisi pour son riche écosystème + (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - utilisé pour sa résolution rapide des + dépendances et son temps de construction +- [Rod](https://github.com/go-rod/rod) - automatisation du navigateur sans tête + pour les modifications d'authentification et d'interrogation +- [SQLite](https://github.com/mattn/go-sqlite3) - utilisé pour stocker les + correspondances, les sessions et les profils +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + un flux http pour envoyer des mises à jour de suivi aux sources du navigateur + OBS +- [i18next](https://github.com/i18next/) - avec connecteur backend pour servir + les objets de localisation de la couche Go +- [xstate](https://github.com/statelyai/xstate) - machines à états pour le + processus d'authentification et le suivi diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..568c964b70e --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx @@ -0,0 +1,42 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Suivez les +matchs en direct de n'importe quel profil Street Fighter 6 ou V CFN. Consultez +[le site Web](https://cfn.williamsjokvist.se/) pour commencer. + +## Caractéristiques + +- Suivi des matchs en temps réel +- Stockage des journaux de match et des statistiques +- Prise en charge de l'affichage des statistiques en direct sur OBS via la + source du navigateur +- Prise en charge de SF6 et SFV +- Possibilité pour les utilisateurs de créer leurs propres thèmes de navigateur + OBS avec CSS + +### Technologie majeure utilisée aux côtés de Wails + +- [Tâche](https://github.com/go-task/task) - encapsulation de la CLI Wails pour + rendre les commandes courantes faciles à utiliser +- [React](https://github.com/facebook/react) - choisi pour son riche écosystème + (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - utilisé pour sa résolution rapide des + dépendances et son temps de construction +- [Rod](https://github.com/go-rod/rod) - automatisation du navigateur sans tête + pour les modifications d'authentification et d'interrogation +- [SQLite](https://github.com/mattn/go-sqlite3) - utilisé pour stocker les + correspondances, les sessions et les profils +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + un flux http pour envoyer des mises à jour de suivi aux sources du navigateur + OBS +- [i18next](https://github.com/i18next/) - avec connecteur backend pour servir + les objets de localisation de la couche Go +- [xstate](https://github.com/statelyai/xstate) - machines à états pour le + processus d'authentification et le suivi diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..568c964b70e --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx @@ -0,0 +1,42 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Suivez les +matchs en direct de n'importe quel profil Street Fighter 6 ou V CFN. Consultez +[le site Web](https://cfn.williamsjokvist.se/) pour commencer. + +## Caractéristiques + +- Suivi des matchs en temps réel +- Stockage des journaux de match et des statistiques +- Prise en charge de l'affichage des statistiques en direct sur OBS via la + source du navigateur +- Prise en charge de SF6 et SFV +- Possibilité pour les utilisateurs de créer leurs propres thèmes de navigateur + OBS avec CSS + +### Technologie majeure utilisée aux côtés de Wails + +- [Tâche](https://github.com/go-task/task) - encapsulation de la CLI Wails pour + rendre les commandes courantes faciles à utiliser +- [React](https://github.com/facebook/react) - choisi pour son riche écosystème + (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - utilisé pour sa résolution rapide des + dépendances et son temps de construction +- [Rod](https://github.com/go-rod/rod) - automatisation du navigateur sans tête + pour les modifications d'authentification et d'interrogation +- [SQLite](https://github.com/mattn/go-sqlite3) - utilisé pour stocker les + correspondances, les sessions et les profils +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + un flux http pour envoyer des mises à jour de suivi aux sources du navigateur + OBS +- [i18next](https://github.com/i18next/) - avec connecteur backend pour servir + les objets de localisation de la couche Go +- [xstate](https://github.com/statelyai/xstate) - machines à états pour le + processus d'authentification et le suivi diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..e451971b98c --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx @@ -0,0 +1,39 @@ +# CFN トラッカー + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - ストリートファイ +ター 6 または V CFN プロフィールのライブマッチを追跡します。 開始するには +、[Web サイト](https://cfn.williamsjokvist.se/) を確認してください。 + +## 特徴 + +- リアルタイムの試合追跡 +- 試合ログと統計の保存 +- ブラウザソース経由で OBS にライブ統計を表示するためのサポート +- SF6 と SFV の両方をサポート +- ユーザーが CSS を使用して独自の OBS ブラウザ テーマを作成できる機能 + +### Wails とともに使用される主要なテクノロジー + +- [タスク](https://github.com/go-task/task) - Wails CLI をラップして一般的なコマ + ンドを使いやすくする +- [React](https://github.com/facebook/react) - 豊富なエコシステム (基数、フレー + マーモーション) で選ばれました +- [Bun](https://github.com/oven-sh/bun) - 依存関係の高速解決とビルド時間に使用さ + れます。 +- [Rod](https://github.com/go-rod/rod) - 認証とポーリングの変更のためのヘッドレ + スブラウザ自動化 +- [SQLite](https://github.com/mattn/go-sqlite3) - 一致、セッション、プロファイル + の保存に使用されます +- [サーバー送信イベント](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + 追跡更新を OBS ブラウザ ソースに送信するための http ストリーム +- [i18next](https://github.com/i18next/) - Go レイヤーからローカリゼーション オ + ブジェクトを提供するバックエンド コネクタを使用 +- [xstate](https://github.com/statelyai/xstate) - 認証プロセスと追跡のためのステ + ート マシン diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..e451971b98c --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx @@ -0,0 +1,39 @@ +# CFN トラッカー + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - ストリートファイ +ター 6 または V CFN プロフィールのライブマッチを追跡します。 開始するには +、[Web サイト](https://cfn.williamsjokvist.se/) を確認してください。 + +## 特徴 + +- リアルタイムの試合追跡 +- 試合ログと統計の保存 +- ブラウザソース経由で OBS にライブ統計を表示するためのサポート +- SF6 と SFV の両方をサポート +- ユーザーが CSS を使用して独自の OBS ブラウザ テーマを作成できる機能 + +### Wails とともに使用される主要なテクノロジー + +- [タスク](https://github.com/go-task/task) - Wails CLI をラップして一般的なコマ + ンドを使いやすくする +- [React](https://github.com/facebook/react) - 豊富なエコシステム (基数、フレー + マーモーション) で選ばれました +- [Bun](https://github.com/oven-sh/bun) - 依存関係の高速解決とビルド時間に使用さ + れます。 +- [Rod](https://github.com/go-rod/rod) - 認証とポーリングの変更のためのヘッドレ + スブラウザ自動化 +- [SQLite](https://github.com/mattn/go-sqlite3) - 一致、セッション、プロファイル + の保存に使用されます +- [サーバー送信イベント](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + 追跡更新を OBS ブラウザ ソースに送信するための http ストリーム +- [i18next](https://github.com/i18next/) - Go レイヤーからローカリゼーション オ + ブジェクトを提供するバックエンド コネクタを使用 +- [xstate](https://github.com/statelyai/xstate) - 認証プロセスと追跡のためのステ + ート マシン diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..e451971b98c --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx @@ -0,0 +1,39 @@ +# CFN トラッカー + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - ストリートファイ +ター 6 または V CFN プロフィールのライブマッチを追跡します。 開始するには +、[Web サイト](https://cfn.williamsjokvist.se/) を確認してください。 + +## 特徴 + +- リアルタイムの試合追跡 +- 試合ログと統計の保存 +- ブラウザソース経由で OBS にライブ統計を表示するためのサポート +- SF6 と SFV の両方をサポート +- ユーザーが CSS を使用して独自の OBS ブラウザ テーマを作成できる機能 + +### Wails とともに使用される主要なテクノロジー + +- [タスク](https://github.com/go-task/task) - Wails CLI をラップして一般的なコマ + ンドを使いやすくする +- [React](https://github.com/facebook/react) - 豊富なエコシステム (基数、フレー + マーモーション) で選ばれました +- [Bun](https://github.com/oven-sh/bun) - 依存関係の高速解決とビルド時間に使用さ + れます。 +- [Rod](https://github.com/go-rod/rod) - 認証とポーリングの変更のためのヘッドレ + スブラウザ自動化 +- [SQLite](https://github.com/mattn/go-sqlite3) - 一致、セッション、プロファイル + の保存に使用されます +- [サーバー送信イベント](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + 追跡更新を OBS ブラウザ ソースに送信するための http ストリーム +- [i18next](https://github.com/i18next/) - Go レイヤーからローカリゼーション オ + ブジェクトを提供するバックエンド コネクタを使用 +- [xstate](https://github.com/statelyai/xstate) - 認証プロセスと追跡のためのステ + ート マシン diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..9d2a86918ba --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx @@ -0,0 +1,39 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN 추적기](https://github.com/williamsjokvist/cfn-tracker) - Street Fighter 6 +또는 V CFN 프로필의 실시간 경기를 추적하세요. 시작하려면 +[웹사이트](https://cfn.williamsjokvist.se/)를 확인하세요. + +## 특징 + +- 실시간 경기 추적 +- 경기 로그 및 통계 저장 +- 브라우저 소스를 통해 OBS에 실시간 통계 표시 지원 +- SF6 및 SFV 모두 지원 +- 사용자가 CSS를 사용하여 자신만의 OBS 브라우저 테마를 만들 수 있는 기능 + +### 웨일스와 함께 사용되는 주요 기술 + +- [작업](https://github.com/go-task/task) - 일반적인 명령을 쉽게 사용할 수 있도 + 록 Wails CLI를 래핑합니다. +- [React](https://github.com/facebook/react) - 풍부한 생태계(radix, 프레이머-모 + 션)로 인해 선택됨 +- [Bun](https://github.com/oven-sh/bun) - 빠른 종속성 해결 및 빌드 시간에 사용됩 + 니다. +- [Rod](https://github.com/go-rod/rod) - 인증 및 폴링 변경을 위한 헤드리스 브라 + 우저 자동화 +- [SQLite](https://github.com/mattn/go-sqlite3) - 경기, 세션 및 프로필을 저장하 + 는 데 사용됩니다. +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + OBS 브라우저 소스에 추적 업데이트를 보내는 http 스트림 +- [i18next](https://github.com/i18next/) - Go 레이어에서 현지화 개체를 제공하기 + 위한 백엔드 커넥터 포함 +- [xstate](https://github.com/statelyai/xstate) - 인증 프로세스 및 추적을 위한 + 상태 머신 diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..9d2a86918ba --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx @@ -0,0 +1,39 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN 추적기](https://github.com/williamsjokvist/cfn-tracker) - Street Fighter 6 +또는 V CFN 프로필의 실시간 경기를 추적하세요. 시작하려면 +[웹사이트](https://cfn.williamsjokvist.se/)를 확인하세요. + +## 특징 + +- 실시간 경기 추적 +- 경기 로그 및 통계 저장 +- 브라우저 소스를 통해 OBS에 실시간 통계 표시 지원 +- SF6 및 SFV 모두 지원 +- 사용자가 CSS를 사용하여 자신만의 OBS 브라우저 테마를 만들 수 있는 기능 + +### 웨일스와 함께 사용되는 주요 기술 + +- [작업](https://github.com/go-task/task) - 일반적인 명령을 쉽게 사용할 수 있도 + 록 Wails CLI를 래핑합니다. +- [React](https://github.com/facebook/react) - 풍부한 생태계(radix, 프레이머-모 + 션)로 인해 선택됨 +- [Bun](https://github.com/oven-sh/bun) - 빠른 종속성 해결 및 빌드 시간에 사용됩 + 니다. +- [Rod](https://github.com/go-rod/rod) - 인증 및 폴링 변경을 위한 헤드리스 브라 + 우저 자동화 +- [SQLite](https://github.com/mattn/go-sqlite3) - 경기, 세션 및 프로필을 저장하 + 는 데 사용됩니다. +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + OBS 브라우저 소스에 추적 업데이트를 보내는 http 스트림 +- [i18next](https://github.com/i18next/) - Go 레이어에서 현지화 개체를 제공하기 + 위한 백엔드 커넥터 포함 +- [xstate](https://github.com/statelyai/xstate) - 인증 프로세스 및 추적을 위한 + 상태 머신 diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..9d2a86918ba --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx @@ -0,0 +1,39 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN 추적기](https://github.com/williamsjokvist/cfn-tracker) - Street Fighter 6 +또는 V CFN 프로필의 실시간 경기를 추적하세요. 시작하려면 +[웹사이트](https://cfn.williamsjokvist.se/)를 확인하세요. + +## 특징 + +- 실시간 경기 추적 +- 경기 로그 및 통계 저장 +- 브라우저 소스를 통해 OBS에 실시간 통계 표시 지원 +- SF6 및 SFV 모두 지원 +- 사용자가 CSS를 사용하여 자신만의 OBS 브라우저 테마를 만들 수 있는 기능 + +### 웨일스와 함께 사용되는 주요 기술 + +- [작업](https://github.com/go-task/task) - 일반적인 명령을 쉽게 사용할 수 있도 + 록 Wails CLI를 래핑합니다. +- [React](https://github.com/facebook/react) - 풍부한 생태계(radix, 프레이머-모 + 션)로 인해 선택됨 +- [Bun](https://github.com/oven-sh/bun) - 빠른 종속성 해결 및 빌드 시간에 사용됩 + 니다. +- [Rod](https://github.com/go-rod/rod) - 인증 및 폴링 변경을 위한 헤드리스 브라 + 우저 자동화 +- [SQLite](https://github.com/mattn/go-sqlite3) - 경기, 세션 및 프로필을 저장하 + 는 데 사용됩니다. +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + OBS 브라우저 소스에 추적 업데이트를 보내는 http 스트림 +- [i18next](https://github.com/i18next/) - Go 레이어에서 현지화 개체를 제공하기 + 위한 백엔드 커넥터 포함 +- [xstate](https://github.com/statelyai/xstate) - 인증 프로세스 및 추적을 위한 + 상태 머신 diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..642dd1ba1d5 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx @@ -0,0 +1,41 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Acompanhe +qualquer partida ao vivo do perfil Street Fighter 6 ou V CFN. Verifique +[o site](https://cfn.williamsjokvist.se/) para começar. + +## Características + +- Acompanhamento de partidas em tempo real +- Armazenamento de registros e estatísticas de partidas +- Suporte para exibição de estatísticas ao vivo no OBS via fonte do navegador +- Suporte para SF6 e SFV +- Capacidade para os usuários criarem seus próprios temas do navegador OBS com + CSS + +### Principais tecnologias usadas junto com Wails + +- [Tarefa](https://github.com/go-task/task) - agrupando a CLI do Wails para + facilitar o uso de comandos comuns +- [React](https://github.com/facebook/react) - escolhido por seu rico + ecossistema (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - usado por sua rápida resolução de + dependências e tempo de construção +- [Rod](https://github.com/go-rod/rod) - automação de navegador headless para + autenticação e alterações de pesquisa +- [SQLite](https://github.com/mattn/go-sqlite3) - usado para armazenar + correspondências, sessões e perfis +- [Eventos enviados pelo servidor](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + um fluxo http para enviar atualizações de rastreamento para fontes do + navegador OBS +- [i18next](https://github.com/i18next/) - com conector de back-end para servir + objetos de localização da camada Go +- [xstate](https://github.com/statelyai/xstate) - máquinas de estado para + processo de autenticação e rastreamento diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..642dd1ba1d5 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx @@ -0,0 +1,41 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Acompanhe +qualquer partida ao vivo do perfil Street Fighter 6 ou V CFN. Verifique +[o site](https://cfn.williamsjokvist.se/) para começar. + +## Características + +- Acompanhamento de partidas em tempo real +- Armazenamento de registros e estatísticas de partidas +- Suporte para exibição de estatísticas ao vivo no OBS via fonte do navegador +- Suporte para SF6 e SFV +- Capacidade para os usuários criarem seus próprios temas do navegador OBS com + CSS + +### Principais tecnologias usadas junto com Wails + +- [Tarefa](https://github.com/go-task/task) - agrupando a CLI do Wails para + facilitar o uso de comandos comuns +- [React](https://github.com/facebook/react) - escolhido por seu rico + ecossistema (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - usado por sua rápida resolução de + dependências e tempo de construção +- [Rod](https://github.com/go-rod/rod) - automação de navegador headless para + autenticação e alterações de pesquisa +- [SQLite](https://github.com/mattn/go-sqlite3) - usado para armazenar + correspondências, sessões e perfis +- [Eventos enviados pelo servidor](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + um fluxo http para enviar atualizações de rastreamento para fontes do + navegador OBS +- [i18next](https://github.com/i18next/) - com conector de back-end para servir + objetos de localização da camada Go +- [xstate](https://github.com/statelyai/xstate) - máquinas de estado para + processo de autenticação e rastreamento diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..642dd1ba1d5 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx @@ -0,0 +1,41 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Acompanhe +qualquer partida ao vivo do perfil Street Fighter 6 ou V CFN. Verifique +[o site](https://cfn.williamsjokvist.se/) para começar. + +## Características + +- Acompanhamento de partidas em tempo real +- Armazenamento de registros e estatísticas de partidas +- Suporte para exibição de estatísticas ao vivo no OBS via fonte do navegador +- Suporte para SF6 e SFV +- Capacidade para os usuários criarem seus próprios temas do navegador OBS com + CSS + +### Principais tecnologias usadas junto com Wails + +- [Tarefa](https://github.com/go-task/task) - agrupando a CLI do Wails para + facilitar o uso de comandos comuns +- [React](https://github.com/facebook/react) - escolhido por seu rico + ecossistema (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - usado por sua rápida resolução de + dependências e tempo de construção +- [Rod](https://github.com/go-rod/rod) - automação de navegador headless para + autenticação e alterações de pesquisa +- [SQLite](https://github.com/mattn/go-sqlite3) - usado para armazenar + correspondências, sessões e perfis +- [Eventos enviados pelo servidor](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + um fluxo http para enviar atualizações de rastreamento para fontes do + navegador OBS +- [i18next](https://github.com/i18next/) - com conector de back-end para servir + objetos de localização da camada Go +- [xstate](https://github.com/statelyai/xstate) - máquinas de estado para + processo de autenticação e rastreamento diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..430f02c8327 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx @@ -0,0 +1,41 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) — отслеживайте +живые матчи любого профиля Street Fighter 6 или V CFN. Чтобы начать, посетите +[веб-сайт](https://cfn.williamsjokvist.se/). + +## Функции + +- Отслеживание матчей в режиме реального времени +- Хранение журналов матчей и статистики +- Поддержка отображения статистики в реальном времени в OBS через источник + браузера. +- Поддержка как SF6, так и SFV. +- Возможность для пользователей создавать свои собственные темы браузера OBS с + помощью CSS. + +### Основные технологии, используемые вместе с Wails + +- [Задача](https://github.com/go-task/task) - перенос Wails CLI для упрощения + использования общих команд. +- [React](https://github.com/facebook/react) — выбран из-за богатой экосистемы + (radix,framer-motion) +- [Bun](https://github.com/oven-sh/bun) – используется для быстрого разрешения + зависимостей и времени сборки. +- [Rod](https://github.com/go-rod/rod) – автономная автоматизация браузера для + аутентификации и опроса изменений. +- [SQLite](https://github.com/mattn/go-sqlite3) - используется для хранения + совпадений, сессий и профилей. +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) + – http-поток для отправки обновлений отслеживания в источники браузера OBS. +- [i18next](https://github.com/i18next/) - с бэкэнд-коннектором для обслуживания + объектов локализации из слоя Go. +- [xstate](https://github.com/statelyai/xstate) — конечные автоматы для процесса + аутентификации и отслеживания. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..430f02c8327 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx @@ -0,0 +1,41 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) — отслеживайте +живые матчи любого профиля Street Fighter 6 или V CFN. Чтобы начать, посетите +[веб-сайт](https://cfn.williamsjokvist.se/). + +## Функции + +- Отслеживание матчей в режиме реального времени +- Хранение журналов матчей и статистики +- Поддержка отображения статистики в реальном времени в OBS через источник + браузера. +- Поддержка как SF6, так и SFV. +- Возможность для пользователей создавать свои собственные темы браузера OBS с + помощью CSS. + +### Основные технологии, используемые вместе с Wails + +- [Задача](https://github.com/go-task/task) - перенос Wails CLI для упрощения + использования общих команд. +- [React](https://github.com/facebook/react) — выбран из-за богатой экосистемы + (radix,framer-motion) +- [Bun](https://github.com/oven-sh/bun) – используется для быстрого разрешения + зависимостей и времени сборки. +- [Rod](https://github.com/go-rod/rod) – автономная автоматизация браузера для + аутентификации и опроса изменений. +- [SQLite](https://github.com/mattn/go-sqlite3) - используется для хранения + совпадений, сессий и профилей. +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) + – http-поток для отправки обновлений отслеживания в источники браузера OBS. +- [i18next](https://github.com/i18next/) - с бэкэнд-коннектором для обслуживания + объектов локализации из слоя Go. +- [xstate](https://github.com/statelyai/xstate) — конечные автоматы для процесса + аутентификации и отслеживания. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..430f02c8327 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx @@ -0,0 +1,41 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) — отслеживайте +живые матчи любого профиля Street Fighter 6 или V CFN. Чтобы начать, посетите +[веб-сайт](https://cfn.williamsjokvist.se/). + +## Функции + +- Отслеживание матчей в режиме реального времени +- Хранение журналов матчей и статистики +- Поддержка отображения статистики в реальном времени в OBS через источник + браузера. +- Поддержка как SF6, так и SFV. +- Возможность для пользователей создавать свои собственные темы браузера OBS с + помощью CSS. + +### Основные технологии, используемые вместе с Wails + +- [Задача](https://github.com/go-task/task) - перенос Wails CLI для упрощения + использования общих команд. +- [React](https://github.com/facebook/react) — выбран из-за богатой экосистемы + (radix,framer-motion) +- [Bun](https://github.com/oven-sh/bun) – используется для быстрого разрешения + зависимостей и времени сборки. +- [Rod](https://github.com/go-rod/rod) – автономная автоматизация браузера для + аутентификации и опроса изменений. +- [SQLite](https://github.com/mattn/go-sqlite3) - используется для хранения + совпадений, сессий и профилей. +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) + – http-поток для отправки обновлений отслеживания в источники браузера OBS. +- [i18next](https://github.com/i18next/) - с бэкэнд-коннектором для обслуживания + объектов локализации из слоя Go. +- [xstate](https://github.com/statelyai/xstate) — конечные автоматы для процесса + аутентификации и отслеживания. diff --git a/website/i18n/vi/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx b/website/i18n/vi/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..d3294c3a5eb --- /dev/null +++ b/website/i18n/vi/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx @@ -0,0 +1,39 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Theo dõi mọi +trận đấu trực tiếp của hồ sơ Street Fighter 6 hoặc V CFN. Hãy kiểm tra +[trang web](https://cfn.williamsjokvist.se/) để bắt đầu. + +## Đặc trưng + +- Theo dõi trận đấu theo thời gian thực +- Lưu trữ nhật ký trận đấu và số liệu thống kê +- Hỗ trợ hiển thị số liệu thống kê trực tiếp lên OBS thông qua Nguồn trình duyệt +- Hỗ trợ cả SF6 và SFV +- Khả năng người dùng tạo chủ đề Trình duyệt OBS của riêng mình bằng CSS + +### Công nghệ chính được sử dụng cùng với Wails + +- [Task](https://github.com/go-task/task) - gói Wails CLI để làm cho các lệnh + phổ biến trở nên dễ sử dụng +- [React](https://github.com/facebook/react) - được chọn vì hệ sinh thái phong + phú (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - được sử dụng để giải quyết phần phụ + thuộc nhanh chóng và thời gian xây dựng +- [Rod](https://github.com/go-rod/rod) - tự động hóa trình duyệt không có đầu để + thay đổi xác thực và bỏ phiếu +- [SQLite](https://github.com/mattn/go-sqlite3) - dùng để lưu trữ các trận đấu, + phiên và hồ sơ +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + luồng http để gửi thông tin cập nhật theo dõi tới các nguồn trình duyệt OBS +- [i18next](https://github.com/i18next/) - với trình kết nối phụ trợ để phục vụ + các đối tượng bản địa hóa từ lớp Go +- [xstate](https://github.com/statelyai/xstate) - máy trạng thái để theo dõi và + xử lý xác thực diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..5e1597d70af --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx @@ -0,0 +1,35 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - 跟踪任何《街头霸 +王 6》或 V CFN 个人资料的实时比赛。 检查[网站](https://cfn.williamsjokvist.se/) +开始。 + +## 特征 + +- 实时比赛追踪 +- 存储比赛日志和统计数据 +- 支持通过浏览器源向 OBS 显示实时统计数据 +- 支持 SF6 和 SFV +- 用户能够使用 CSS 创建自己的 OBS 浏览器主题 + +### 与 Wails 一起使用的主要技术 + +- [Task](https://github.com/go-task/task) - 包装 Wails CLI 以使常用命令易于使用 +- [React](https://github.com/facebook/react) - 因其丰富的生态系统而被选中 + (radix、framer-motion) +- [Bun](https://github.com/oven-sh/bun) - 用于快速依赖解析和构建时间 +- [Rod](https://github.com/go-rod/rod) - 用于身份验证和轮询更改的无头浏览器自动 + 化 +- [SQLite](https://github.com/mattn/go-sqlite3) - 用于存储匹配、会话和配置文件 +- [服务器发送事件](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + 用于向 OBS 浏览器源发送跟踪更新的 http 流 +- [i18next](https://github.com/i18next/) - 使用后端连接器来服务来自 Go 层的本地 + 化对象 +- [xstate](https://github.com/statelyai/xstate) - 用于身份验证过程和跟踪的状态机 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..5e1597d70af --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.6.0/community/showcase/cfntracker.mdx @@ -0,0 +1,35 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - 跟踪任何《街头霸 +王 6》或 V CFN 个人资料的实时比赛。 检查[网站](https://cfn.williamsjokvist.se/) +开始。 + +## 特征 + +- 实时比赛追踪 +- 存储比赛日志和统计数据 +- 支持通过浏览器源向 OBS 显示实时统计数据 +- 支持 SF6 和 SFV +- 用户能够使用 CSS 创建自己的 OBS 浏览器主题 + +### 与 Wails 一起使用的主要技术 + +- [Task](https://github.com/go-task/task) - 包装 Wails CLI 以使常用命令易于使用 +- [React](https://github.com/facebook/react) - 因其丰富的生态系统而被选中 + (radix、framer-motion) +- [Bun](https://github.com/oven-sh/bun) - 用于快速依赖解析和构建时间 +- [Rod](https://github.com/go-rod/rod) - 用于身份验证和轮询更改的无头浏览器自动 + 化 +- [SQLite](https://github.com/mattn/go-sqlite3) - 用于存储匹配、会话和配置文件 +- [服务器发送事件](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + 用于向 OBS 浏览器源发送跟踪更新的 http 流 +- [i18next](https://github.com/i18next/) - 使用后端连接器来服务来自 Go 层的本地 + 化对象 +- [xstate](https://github.com/statelyai/xstate) - 用于身份验证过程和跟踪的状态机 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..5e1597d70af --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.7.0/community/showcase/cfntracker.mdx @@ -0,0 +1,35 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - 跟踪任何《街头霸 +王 6》或 V CFN 个人资料的实时比赛。 检查[网站](https://cfn.williamsjokvist.se/) +开始。 + +## 特征 + +- 实时比赛追踪 +- 存储比赛日志和统计数据 +- 支持通过浏览器源向 OBS 显示实时统计数据 +- 支持 SF6 和 SFV +- 用户能够使用 CSS 创建自己的 OBS 浏览器主题 + +### 与 Wails 一起使用的主要技术 + +- [Task](https://github.com/go-task/task) - 包装 Wails CLI 以使常用命令易于使用 +- [React](https://github.com/facebook/react) - 因其丰富的生态系统而被选中 + (radix、framer-motion) +- [Bun](https://github.com/oven-sh/bun) - 用于快速依赖解析和构建时间 +- [Rod](https://github.com/go-rod/rod) - 用于身份验证和轮询更改的无头浏览器自动 + 化 +- [SQLite](https://github.com/mattn/go-sqlite3) - 用于存储匹配、会话和配置文件 +- [服务器发送事件](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + 用于向 OBS 浏览器源发送跟踪更新的 http 流 +- [i18next](https://github.com/i18next/) - 使用后端连接器来服务来自 Go 层的本地 + 化对象 +- [xstate](https://github.com/statelyai/xstate) - 用于身份验证过程和跟踪的状态机 diff --git a/website/static/img/showcase/cfntracker.webp b/website/static/img/showcase/cfntracker.webp new file mode 100644 index 0000000000000000000000000000000000000000..c596e3c6a1d50f0746feda4febfbdc86d546ac61 GIT binary patch literal 93970 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

t_ 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 z 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 literal 0 HcmV?d00001 diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/cfntracker.mdx b/website/versioned_docs/version-v2.6.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..8fab23b75ad --- /dev/null +++ b/website/versioned_docs/version-v2.6.0/community/showcase/cfntracker.mdx @@ -0,0 +1,39 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Track any Street +Fighter 6 or V CFN profile's live matches. Check +[the website](https://cfn.williamsjokvist.se/) to get started. + +## Features + +- Real-time match tracking +- Storing match logs and statistics +- Support for displaying live stats to OBS via Browser Source +- Support for both SF6 and SFV +- Ability for users to create their own OBS Browser themes with CSS + +### Major tech used alongside Wails + +- [Task](https://github.com/go-task/task) - wrapping the Wails CLI to make + common commands easy to use +- [React](https://github.com/facebook/react) - chosen for its rich ecosystem + (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - used for its fast dependency + resolution and build-time +- [Rod](https://github.com/go-rod/rod) - headless browser automation for + authentication and polling changes +- [SQLite](https://github.com/mattn/go-sqlite3) - used for storing matches, + sessions and profiles +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + a http stream to send tracking updates to OBS browser sources +- [i18next](https://github.com/i18next/) - with backend connector to serve + localization objects from the Go layer +- [xstate](https://github.com/statelyai/xstate) - state machines for auth + process and tracking diff --git a/website/versioned_docs/version-v2.7.0/community/showcase/cfntracker.mdx b/website/versioned_docs/version-v2.7.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..8fab23b75ad --- /dev/null +++ b/website/versioned_docs/version-v2.7.0/community/showcase/cfntracker.mdx @@ -0,0 +1,39 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Track any Street +Fighter 6 or V CFN profile's live matches. Check +[the website](https://cfn.williamsjokvist.se/) to get started. + +## Features + +- Real-time match tracking +- Storing match logs and statistics +- Support for displaying live stats to OBS via Browser Source +- Support for both SF6 and SFV +- Ability for users to create their own OBS Browser themes with CSS + +### Major tech used alongside Wails + +- [Task](https://github.com/go-task/task) - wrapping the Wails CLI to make + common commands easy to use +- [React](https://github.com/facebook/react) - chosen for its rich ecosystem + (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - used for its fast dependency + resolution and build-time +- [Rod](https://github.com/go-rod/rod) - headless browser automation for + authentication and polling changes +- [SQLite](https://github.com/mattn/go-sqlite3) - used for storing matches, + sessions and profiles +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + a http stream to send tracking updates to OBS browser sources +- [i18next](https://github.com/i18next/) - with backend connector to serve + localization objects from the Go layer +- [xstate](https://github.com/statelyai/xstate) - state machines for auth + process and tracking From a98869193122f7d8b159b232e5ce22ebe885a3b5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 27 Jan 2024 08:43:22 +1100 Subject: [PATCH 021/369] chore: update sponsors.svg (#3218) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 48 ++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index 7ad5a6bd4b6..1bef13e74c7 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -28,24 +28,28 @@ text { Simon Thomas
Covering Costs - Nick - + Nick + - Marcus - + Marcus + - John - + John + - Matt Holt - + Matt Holt + - Iain - + Iain + + + + Julien + Buying Breakfast tc-hib @@ -121,46 +125,42 @@ text { Helpers - + - + - + - + - + - + - + - + - + - - - - - + From 9b35616a20acd335a043347f8cd919c5fb84589d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 21:33:29 +1100 Subject: [PATCH 022/369] chore: update sponsors.svg (#3223) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index 1bef13e74c7..14cec99e067 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -125,42 +125,46 @@ text { Helpers - + - + - + - + - + + + + + - + - + - + - + - + From 9903ba70d5183376a7073e9259576165a95db3f5 Mon Sep 17 00:00:00 2001 From: atterpac <89053530+atterpac@users.noreply.github.com> Date: Sun, 4 Feb 2024 22:12:09 -0800 Subject: [PATCH 023/369] Update vue-tsc (#3234) changelog --- v2/pkg/templates/templates/vue-ts/frontend/package.json | 4 ++-- website/src/pages/changelog.mdx | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/v2/pkg/templates/templates/vue-ts/frontend/package.json b/v2/pkg/templates/templates/vue-ts/frontend/package.json index c06165c24e2..e65d0eff441 100644 --- a/v2/pkg/templates/templates/vue-ts/frontend/package.json +++ b/v2/pkg/templates/templates/vue-ts/frontend/package.json @@ -15,7 +15,7 @@ "@vitejs/plugin-vue": "^3.0.3", "typescript": "^4.6.4", "vite": "^3.0.7", - "vue-tsc": "^0.39.5", + "vue-tsc": "^1.8.27", "@babel/types": "^7.18.10" } -} \ No newline at end of file +} diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index f8868d4290b..cfc07a04bd1 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -24,6 +24,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add dock icon right-click exit handling by @almas1992 in [PR](https://github.com/wailsapp/wails/pull/3157) ### Fixed +- Fixed vue-ts template build error. Fixed by @atterpac in +[PR](https://github.com/wailsapp/wails/pull/3243) - Docs for IsZoomControlEnabled and ZoomFactor. Fixed by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/3137) - Fixed `-compiler` flag for `wails build`, `wails dev` and `wails generate module`. Fixed in [PR](https://github.com/wailsapp/wails/pull/3121) by [@xtrafrancyz](https://github.com/xtrafrancyz) - Fixed uninitialized `SecondInstanceData.WorkingDirectory` on linux and windows ([#3154](https://github.com/wailsapp/wails/pull/3154)). From 72e12ef39825085a08c80aaa348b42af2eac7f46 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 22:41:20 +1100 Subject: [PATCH 024/369] chore: update sponsors.svg (#3235) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index 14cec99e067..f077852c289 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -125,46 +125,50 @@ text { Helpers - + - + - + - + - + - + - + - + - + - + - + + + + + From e29b375de5d5f31da46b097c76087a7644fa2f6d Mon Sep 17 00:00:00 2001 From: stffabi Date: Thu, 8 Feb 2024 12:40:04 +0100 Subject: [PATCH 025/369] [cli] Bump x/tools to 0.17.0 to fix compatiblity with go 1.22 (#3244) --- v2/go.mod | 12 ++++++------ v2/go.sum | 26 +++++++++++++------------- website/src/pages/changelog.mdx | 1 + 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/v2/go.mod b/v2/go.mod index a38dd1a2282..5061144903f 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -39,10 +39,10 @@ require ( github.com/wailsapp/go-webview2 v1.0.10 github.com/wailsapp/mimetype v1.4.1 github.com/wzshiming/ctc v1.2.3 - golang.org/x/mod v0.12.0 - golang.org/x/net v0.19.0 - golang.org/x/sys v0.15.0 - golang.org/x/tools v0.13.0 + golang.org/x/mod v0.14.0 + golang.org/x/net v0.20.0 + golang.org/x/sys v0.16.0 + golang.org/x/tools v0.17.0 ) require ( @@ -97,10 +97,10 @@ require ( github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/yuin/goldmark v1.4.13 // indirect github.com/yuin/goldmark-emoji v1.0.1 // indirect - golang.org/x/crypto v0.17.0 // indirect + golang.org/x/crypto v0.18.0 // indirect golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/image v0.12.0 // indirect - golang.org/x/term v0.15.0 // indirect + golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/v2/go.sum b/v2/go.sum index b9b7eb62073..4b6fb083189 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -245,8 +245,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -254,8 +254,8 @@ golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ= golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -265,12 +265,12 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -297,8 +297,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -306,8 +306,8 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -322,8 +322,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index cfc07a04bd1..42baf728adc 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed `-compiler` flag for `wails build`, `wails dev` and `wails generate module`. Fixed in [PR](https://github.com/wailsapp/wails/pull/3121) by [@xtrafrancyz](https://github.com/xtrafrancyz) - Fixed uninitialized `SecondInstanceData.WorkingDirectory` on linux and windows ([#3154](https://github.com/wailsapp/wails/pull/3154)). - Fixed save file dialog not appending file extension automatically on Windows by @almas1992 in [PR](https://github.com/wailsapp/wails/pull/3205) +- Fixed compatibility for wails cli being built with go 1.22 and later. Fixed by @stffabi in [PR](https://github.com/wailsapp/wails/pull/3244) ## v2.7.1 - 2023-12-10 From 772f870eb38d6f9330597a2843a19fa76d706c0e Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 8 Feb 2024 21:28:28 +1100 Subject: [PATCH 026/369] v2.8.0 --- v2/cmd/wails/internal/version.txt | 2 +- .../version-v2.8.0.json | 38 + .../version-v2.8.0/community/links.mdx | 26 + .../community/showcase/bulletinboard.mdx | 10 + .../community/showcase/cfntracker.mdx | 42 + .../community/showcase/emailit.mdx | 10 + .../community/showcase/encrypteasy.mdx | 12 + .../community/showcase/espstudio.mdx | 13 + .../community/showcase/filehound.mdx | 16 + .../community/showcase/hiposter.mdx | 10 + .../community/showcase/minecraftupdater.mdx | 14 + .../community/showcase/modalfilemanager.mdx | 14 + .../community/showcase/mollywallet.mdx | 10 + .../community/showcase/october.mdx | 14 + .../community/showcase/optimus.mdx | 10 + .../community/showcase/portfall.mdx | 10 + .../community/showcase/restic-browser.mdx | 12 + .../community/showcase/riftshare.mdx | 21 + .../community/showcase/scriptbar.mdx | 10 + .../community/showcase/surge.mdx | 10 + .../community/showcase/tinyrdm.mdx | 11 + .../community/showcase/wally.mdx | 10 + .../community/showcase/warmine.mdx | 19 + .../community/showcase/wombat.mdx | 10 + .../version-v2.8.0/community/showcase/ytd.mdx | 10 + .../version-v2.8.0/community/templates.mdx | 69 ++ .../gettingstarted/building.mdx | 22 + .../gettingstarted/development.mdx | 16 + .../gettingstarted/firstproject.mdx | 130 +++ .../gettingstarted/installation.mdx | 90 ++ .../version-v2.8.0/guides/angular.mdx | 14 + .../guides/application-development.mdx | 215 +++++ .../guides/crossplatform-build.mdx | 66 ++ .../guides/custom-protocol-schemes.mdx | 204 ++++ .../version-v2.8.0/guides/dynamic-assets.mdx | 136 +++ .../guides/file-association.mdx | 244 +++++ .../version-v2.8.0/guides/frameless.mdx | 87 ++ .../version-v2.8.0/guides/frontend.mdx | 72 ++ .../version-v2.8.0/guides/ides.mdx | 127 +++ .../guides/linux-distro-support.mdx | 103 +++ .../version-v2.8.0/guides/linux.mdx | 18 + .../guides/local-development.mdx | 55 ++ .../version-v2.8.0/guides/mac-appstore.mdx | 97 ++ .../version-v2.8.0/guides/manual-builds.mdx | 95 ++ .../version-v2.8.0/guides/migrating.mdx | 191 ++++ .../version-v2.8.0/guides/mouse-buttons.mdx | 25 + .../version-v2.8.0/guides/obfuscated.mdx | 40 + .../version-v2.8.0/guides/overscroll.mdx | 10 + .../version-v2.8.0}/guides/routing.mdx | 0 .../version-v2.8.0/guides/signing.mdx | 387 ++++++++ .../guides/single-instance-lock.mdx | 81 ++ .../version-v2.8.0/guides/sveltekit.mdx | 153 +++ .../version-v2.8.0/guides/templates.mdx | 97 ++ .../version-v2.8.0/guides/troubleshooting.mdx | 368 ++++++++ .../version-v2.8.0/guides/vscode.mdx | 82 ++ .../guides/windows-installer.mdx | 58 ++ .../version-v2.8.0/guides/windows.mdx | 61 ++ .../version-v2.8.0/howdoesitwork.mdx | 369 ++++++++ .../version-v2.8.0/introduction.mdx | 75 ++ .../version-v2.8.0/reference/cli.mdx | 241 +++++ .../version-v2.8.0/reference/menus.mdx | 230 +++++ .../version-v2.8.0/reference/options.mdx | 853 +++++++++++++++++ .../reference/project-config.mdx | 92 ++ .../reference/runtime/browser.mdx | 13 + .../reference/runtime/clipboard.mdx | 23 + .../reference/runtime/dialog.mdx | 302 ++++++ .../reference/runtime/events.mdx | 37 + .../reference/runtime/intro.mdx | 85 ++ .../version-v2.8.0/reference/runtime/log.mdx | 130 +++ .../version-v2.8.0/reference/runtime/menu.mdx | 25 + .../reference/runtime/screen.mdx | 38 + .../reference/runtime/window.mdx | 227 +++++ .../version-v2.8.0/tutorials/dogsapi.mdx | 245 +++++ .../version-v2.8.0/tutorials/helloworld.mdx | 123 +++ .../version-v2.8.0}/appendix/_category_.json | 0 .../version-v2.8.0}/community/_category_.json | 0 .../version-v2.8.0/community/links.mdx | 26 + .../community/showcase/_category_.json | 0 .../community/showcase/bulletinboard.mdx | 10 + .../community/showcase/cfntracker.mdx | 39 + .../community/showcase/emailit.mdx | 10 + .../community/showcase/encrypteasy.mdx | 12 + .../community/showcase/espstudio.mdx | 13 + .../community/showcase/filehound.mdx | 16 + .../community/showcase/hiposter.mdx | 10 + .../community/showcase/minecraftupdater.mdx | 14 + .../community/showcase/modalfilemanager.mdx | 14 + .../community/showcase/mollywallet.mdx | 10 + .../community/showcase/october.mdx | 14 + .../community/showcase/optimus.mdx | 10 + .../community/showcase/portfall.mdx | 10 + .../community/showcase/restic-browser.mdx | 12 + .../community/showcase/riftshare.mdx | 21 + .../community/showcase/scriptbar.mdx | 10 + .../community/showcase/surge.mdx | 10 + .../community/showcase/tinyrdm.mdx | 11 + .../community/showcase/wally.mdx | 10 + .../community/showcase/warmine.mdx | 19 + .../community/showcase/wombat.mdx | 10 + .../version-v2.8.0/community/showcase/ytd.mdx | 10 + .../version-v2.8.0/community/templates.mdx | 69 ++ .../gettingstarted/_category_.json | 0 .../gettingstarted/building.mdx | 22 + .../gettingstarted/development.mdx | 16 + .../gettingstarted/firstproject.mdx | 130 +++ .../gettingstarted/installation.mdx | 89 ++ .../version-v2.8.0}/guides/_category_.json | 0 .../version-v2.8.0/guides/angular.mdx | 14 + .../guides/application-development.mdx | 215 +++++ .../guides/crossplatform-build.mdx | 66 ++ .../guides/custom-protocol-schemes.mdx | 204 ++++ .../version-v2.8.0/guides/dynamic-assets.mdx | 136 +++ .../guides/file-association.mdx | 244 +++++ .../version-v2.8.0/guides/frameless.mdx | 87 ++ .../version-v2.8.0/guides/frontend.mdx | 72 ++ .../version-v2.8.0/guides/ides.mdx | 127 +++ .../guides/linux-distro-support.mdx | 103 +++ .../version-v2.8.0/guides/linux.mdx | 18 + .../guides/local-development.mdx | 55 ++ .../version-v2.8.0/guides/mac-appstore.mdx | 97 ++ .../version-v2.8.0/guides/manual-builds.mdx | 95 ++ .../version-v2.8.0/guides/migrating.mdx | 191 ++++ .../version-v2.8.0/guides/mouse-buttons.mdx | 25 + .../version-v2.8.0/guides/obfuscated.mdx | 40 + .../version-v2.8.0/guides/overscroll.mdx | 10 + .../version-v2.8.0/guides/routing.mdx | 47 + .../version-v2.8.0/guides/signing.mdx | 387 ++++++++ .../guides/single-instance-lock.mdx | 81 ++ .../version-v2.8.0/guides/sveltekit.mdx | 153 +++ .../version-v2.8.0/guides/templates.mdx | 97 ++ .../version-v2.8.0/guides/troubleshooting.mdx | 368 ++++++++ .../version-v2.8.0/guides/vscode.mdx | 82 ++ .../guides/windows-installer.mdx | 58 ++ .../version-v2.8.0/guides/windows.mdx | 61 ++ .../version-v2.8.0/howdoesitwork.mdx | 369 ++++++++ .../version-v2.8.0/introduction.mdx | 75 ++ .../version-v2.8.0}/reference/_category_.json | 0 .../version-v2.8.0/reference/cli.mdx | 240 +++++ .../version-v2.8.0/reference/menus.mdx | 230 +++++ .../version-v2.8.0/reference/options.mdx | 853 +++++++++++++++++ .../reference/project-config.mdx | 91 ++ .../reference/runtime/_category_.json | 0 .../reference/runtime/browser.mdx | 13 + .../reference/runtime/clipboard.mdx | 23 + .../reference/runtime/dialog.mdx | 302 ++++++ .../reference/runtime/events.mdx | 37 + .../reference/runtime/intro.mdx | 85 ++ .../version-v2.8.0/reference/runtime/log.mdx | 130 +++ .../version-v2.8.0/reference/runtime/menu.mdx | 25 + .../reference/runtime/screen.mdx | 38 + .../reference/runtime/window.mdx | 227 +++++ .../version-v2.8.0}/tutorials/_category_.json | 0 .../version-v2.8.0/tutorials/dogsapi.mdx | 245 +++++ .../version-v2.8.0/tutorials/helloworld.mdx | 123 +++ .../version-v2.8.0/community/links.mdx | 26 + .../community/showcase/bulletinboard.mdx | 0 .../community/showcase/cfntracker.mdx | 39 + .../community/showcase/emailit.mdx | 0 .../community/showcase/encrypteasy.mdx | 12 + .../community/showcase/espstudio.mdx | 13 + .../community/showcase/filehound.mdx | 16 + .../community/showcase/hiposter.mdx | 10 + .../community/showcase/minecraftupdater.mdx | 14 + .../community/showcase/modalfilemanager.mdx | 14 + .../community/showcase/mollywallet.mdx | 10 + .../community/showcase/october.mdx | 0 .../community/showcase/optimus.mdx | 10 + .../community/showcase/portfall.mdx | 10 + .../community/showcase/restic-browser.mdx | 0 .../community/showcase/riftshare.mdx | 0 .../community/showcase/scriptbar.mdx | 0 .../community/showcase/surge.mdx | 0 .../community/showcase/tinyrdm.mdx | 11 + .../community/showcase/wally.mdx | 0 .../community/showcase/warmine.mdx | 19 + .../community/showcase/wombat.mdx | 10 + .../community/showcase/ytd.mdx | 0 .../version-v2.8.0/community/templates.mdx | 69 ++ .../gettingstarted/building.mdx | 22 + .../gettingstarted/development.mdx | 16 + .../gettingstarted/firstproject.mdx | 130 +++ .../gettingstarted/installation.mdx | 89 ++ .../version-v2.8.0/guides/angular.mdx | 14 + .../guides/application-development.mdx | 215 +++++ .../guides/crossplatform-build.mdx | 66 ++ .../guides/custom-protocol-schemes.mdx | 204 ++++ .../version-v2.8.0/guides/dynamic-assets.mdx | 136 +++ .../guides/file-association.mdx | 244 +++++ .../version-v2.8.0/guides/frameless.mdx | 87 ++ .../version-v2.8.0/guides/frontend.mdx | 72 ++ .../version-v2.8.0/guides/ides.mdx | 127 +++ .../guides/linux-distro-support.mdx | 103 +++ .../version-v2.8.0/guides/linux.mdx | 18 + .../guides/local-development.mdx | 55 ++ .../version-v2.8.0/guides/mac-appstore.mdx | 97 ++ .../version-v2.8.0/guides/manual-builds.mdx | 95 ++ .../version-v2.8.0/guides/migrating.mdx | 191 ++++ .../version-v2.8.0/guides/mouse-buttons.mdx | 25 + .../version-v2.8.0/guides/obfuscated.mdx | 40 + .../version-v2.8.0/guides/overscroll.mdx | 10 + .../version-v2.8.0/guides/routing.mdx | 47 + .../version-v2.8.0/guides/signing.mdx | 387 ++++++++ .../guides/single-instance-lock.mdx | 81 ++ .../version-v2.8.0/guides/sveltekit.mdx | 153 +++ .../version-v2.8.0/guides/templates.mdx | 97 ++ .../version-v2.8.0/guides/troubleshooting.mdx | 368 ++++++++ .../version-v2.8.0/guides/vscode.mdx | 82 ++ .../guides/windows-installer.mdx | 58 ++ .../version-v2.8.0/guides/windows.mdx | 61 ++ .../version-v2.8.0/howdoesitwork.mdx | 369 ++++++++ .../version-v2.8.0/introduction.mdx | 75 ++ .../version-v2.8.0/reference/cli.mdx | 240 +++++ .../version-v2.8.0/reference/menus.mdx | 230 +++++ .../version-v2.8.0/reference/options.mdx | 853 +++++++++++++++++ .../reference/project-config.mdx | 0 .../reference/runtime/browser.mdx | 13 + .../reference/runtime/clipboard.mdx | 23 + .../reference/runtime/dialog.mdx | 302 ++++++ .../reference/runtime/events.mdx | 37 + .../reference/runtime/intro.mdx | 85 ++ .../version-v2.8.0/reference/runtime/log.mdx | 130 +++ .../version-v2.8.0/reference/runtime/menu.mdx | 25 + .../reference/runtime/screen.mdx | 38 + .../reference/runtime/window.mdx | 227 +++++ .../version-v2.8.0/tutorials/dogsapi.mdx | 245 +++++ .../version-v2.8.0/tutorials/helloworld.mdx | 123 +++ .../version-v2.8.0/community/links.mdx | 26 + .../community/showcase/bulletinboard.mdx | 10 + .../community/showcase/cfntracker.mdx | 41 + .../community/showcase/emailit.mdx | 10 + .../community/showcase/encrypteasy.mdx | 12 + .../community/showcase/espstudio.mdx | 13 + .../community/showcase/filehound.mdx | 16 + .../community/showcase/hiposter.mdx | 10 + .../community/showcase/minecraftupdater.mdx | 14 + .../community/showcase/modalfilemanager.mdx | 14 + .../community/showcase/mollywallet.mdx | 10 + .../community/showcase/october.mdx | 14 + .../community/showcase/optimus.mdx | 10 + .../community/showcase/portfall.mdx | 10 + .../community/showcase/restic-browser.mdx | 12 + .../community/showcase/riftshare.mdx | 21 + .../community/showcase/scriptbar.mdx | 10 + .../community/showcase/surge.mdx | 10 + .../community/showcase/tinyrdm.mdx | 11 + .../community/showcase/wally.mdx | 10 + .../community/showcase/warmine.mdx | 19 + .../community/showcase/wombat.mdx | 10 + .../version-v2.8.0/community/showcase/ytd.mdx | 10 + .../version-v2.8.0/community/templates.mdx | 69 ++ .../gettingstarted/building.mdx | 22 + .../gettingstarted/development.mdx | 16 + .../gettingstarted/firstproject.mdx | 130 +++ .../gettingstarted/installation.mdx | 90 ++ .../version-v2.8.0/guides/angular.mdx | 14 + .../guides/application-development.mdx | 215 +++++ .../guides/crossplatform-build.mdx | 66 ++ .../guides/custom-protocol-schemes.mdx | 204 ++++ .../version-v2.8.0/guides/dynamic-assets.mdx | 136 +++ .../guides/file-association.mdx | 244 +++++ .../version-v2.8.0/guides/frameless.mdx | 87 ++ .../version-v2.8.0/guides/frontend.mdx | 72 ++ .../version-v2.8.0/guides/ides.mdx | 127 +++ .../guides/linux-distro-support.mdx | 103 +++ .../version-v2.8.0/guides/linux.mdx | 18 + .../guides/local-development.mdx | 55 ++ .../version-v2.8.0/guides/mac-appstore.mdx | 97 ++ .../version-v2.8.0/guides/manual-builds.mdx | 95 ++ .../version-v2.8.0/guides/migrating.mdx | 191 ++++ .../version-v2.8.0/guides/mouse-buttons.mdx | 25 + .../version-v2.8.0/guides/obfuscated.mdx | 40 + .../version-v2.8.0/guides/overscroll.mdx | 10 + .../version-v2.8.0/guides/routing.mdx | 47 + .../version-v2.8.0/guides/signing.mdx | 387 ++++++++ .../guides/single-instance-lock.mdx | 81 ++ .../version-v2.8.0/guides/sveltekit.mdx | 153 +++ .../version-v2.8.0/guides/templates.mdx | 97 ++ .../version-v2.8.0/guides/troubleshooting.mdx | 368 ++++++++ .../version-v2.8.0/guides/vscode.mdx | 82 ++ .../guides/windows-installer.mdx | 58 ++ .../version-v2.8.0/guides/windows.mdx | 61 ++ .../version-v2.8.0/howdoesitwork.mdx | 369 ++++++++ .../version-v2.8.0/introduction.mdx | 75 ++ .../version-v2.8.0/reference/cli.mdx | 240 +++++ .../version-v2.8.0/reference/menus.mdx | 230 +++++ .../version-v2.8.0/reference/options.mdx | 853 +++++++++++++++++ .../reference/project-config.mdx | 92 ++ .../reference/runtime/browser.mdx | 13 + .../reference/runtime/clipboard.mdx | 23 + .../reference/runtime/dialog.mdx | 302 ++++++ .../reference/runtime/events.mdx | 37 + .../reference/runtime/intro.mdx | 85 ++ .../version-v2.8.0/reference/runtime/log.mdx | 130 +++ .../version-v2.8.0/reference/runtime/menu.mdx | 25 + .../reference/runtime/screen.mdx | 38 + .../reference/runtime/window.mdx | 227 +++++ .../version-v2.8.0/tutorials/dogsapi.mdx | 245 +++++ .../version-v2.8.0/tutorials/helloworld.mdx | 123 +++ .../version-v2.8.0/community/links.mdx | 26 + .../community/showcase/bulletinboard.mdx | 10 + .../community/showcase/cfntracker.mdx | 41 + .../community/showcase/emailit.mdx | 10 + .../community/showcase/encrypteasy.mdx | 12 + .../community/showcase/espstudio.mdx | 13 + .../community/showcase/filehound.mdx | 16 + .../community/showcase/hiposter.mdx | 10 + .../community/showcase/minecraftupdater.mdx | 14 + .../community/showcase/modalfilemanager.mdx | 14 + .../community/showcase/mollywallet.mdx | 10 + .../community/showcase/october.mdx | 14 + .../community/showcase/optimus.mdx | 10 + .../community/showcase/portfall.mdx | 10 + .../community/showcase/restic-browser.mdx | 12 + .../community/showcase/riftshare.mdx | 21 + .../community/showcase/scriptbar.mdx | 10 + .../community/showcase/surge.mdx | 10 + .../community/showcase/tinyrdm.mdx | 11 + .../community/showcase/wally.mdx | 10 + .../community/showcase/warmine.mdx | 19 + .../community/showcase/wombat.mdx | 10 + .../version-v2.8.0/community/showcase/ytd.mdx | 10 + .../version-v2.8.0/community/templates.mdx | 69 ++ .../gettingstarted/building.mdx | 22 + .../gettingstarted/development.mdx | 16 + .../gettingstarted/firstproject.mdx | 130 +++ .../gettingstarted/installation.mdx | 90 ++ .../version-v2.8.0/guides/angular.mdx | 14 + .../guides/application-development.mdx | 215 +++++ .../guides/crossplatform-build.mdx | 66 ++ .../guides/custom-protocol-schemes.mdx | 204 ++++ .../version-v2.8.0/guides/dynamic-assets.mdx | 136 +++ .../guides/file-association.mdx | 244 +++++ .../version-v2.8.0/guides/frameless.mdx | 87 ++ .../version-v2.8.0/guides/frontend.mdx | 72 ++ .../version-v2.8.0/guides/ides.mdx | 127 +++ .../guides/linux-distro-support.mdx | 103 +++ .../version-v2.8.0/guides/linux.mdx | 18 + .../guides/local-development.mdx | 55 ++ .../version-v2.8.0/guides/mac-appstore.mdx | 97 ++ .../version-v2.8.0/guides/manual-builds.mdx | 95 ++ .../version-v2.8.0/guides/migrating.mdx | 191 ++++ .../version-v2.8.0/guides/mouse-buttons.mdx | 25 + .../version-v2.8.0/guides/obfuscated.mdx | 40 + .../version-v2.8.0/guides/overscroll.mdx | 10 + .../version-v2.8.0/guides/routing.mdx | 47 + .../version-v2.8.0/guides/signing.mdx | 387 ++++++++ .../guides/single-instance-lock.mdx | 81 ++ .../version-v2.8.0/guides/sveltekit.mdx | 153 +++ .../version-v2.8.0/guides/templates.mdx | 97 ++ .../version-v2.8.0/guides/troubleshooting.mdx | 368 ++++++++ .../version-v2.8.0/guides/vscode.mdx | 82 ++ .../guides/windows-installer.mdx | 58 ++ .../version-v2.8.0/guides/windows.mdx | 61 ++ .../version-v2.8.0/howdoesitwork.mdx | 369 ++++++++ .../version-v2.8.0/introduction.mdx | 75 ++ .../version-v2.8.0/reference/cli.mdx | 240 +++++ .../version-v2.8.0/reference/menus.mdx | 230 +++++ .../version-v2.8.0/reference/options.mdx | 853 +++++++++++++++++ .../reference/project-config.mdx | 92 ++ .../reference/runtime/browser.mdx | 13 + .../reference/runtime/clipboard.mdx | 23 + .../reference/runtime/dialog.mdx | 302 ++++++ .../reference/runtime/events.mdx | 37 + .../reference/runtime/intro.mdx | 85 ++ .../version-v2.8.0/reference/runtime/log.mdx | 130 +++ .../version-v2.8.0/reference/runtime/menu.mdx | 25 + .../reference/runtime/screen.mdx | 38 + .../reference/runtime/window.mdx | 227 +++++ .../version-v2.8.0/tutorials/dogsapi.mdx | 245 +++++ .../version-v2.8.0/tutorials/helloworld.mdx | 123 +++ .../version-v2.8.0/appendix/_category_.json | 4 + .../version-v2.8.0/community/_category_.json | 4 + .../version-v2.8.0/community/links.mdx | 26 + .../community/showcase/_category_.json | 4 + .../community/showcase/bulletinboard.mdx | 10 + .../community/showcase/cfntracker.mdx | 35 + .../community/showcase/emailit.mdx | 10 + .../community/showcase/encrypteasy.mdx | 12 + .../community/showcase/espstudio.mdx | 13 + .../community/showcase/filehound.mdx | 16 + .../community/showcase/hiposter.mdx | 10 + .../community/showcase/minecraftupdater.mdx | 14 + .../community/showcase/modalfilemanager.mdx | 14 + .../community/showcase/mollywallet.mdx | 10 + .../community/showcase/october.mdx | 14 + .../community/showcase/optimus.mdx | 10 + .../community/showcase/portfall.mdx | 10 + .../community/showcase/restic-browser.mdx | 12 + .../community/showcase/riftshare.mdx | 21 + .../community/showcase/scriptbar.mdx | 10 + .../community/showcase/surge.mdx | 10 + .../community/showcase/tinyrdm.mdx | 11 + .../community/showcase/wally.mdx | 10 + .../community/showcase/warmine.mdx | 19 + .../community/showcase/wombat.mdx | 10 + .../version-v2.8.0/community/showcase/ytd.mdx | 10 + .../version-v2.8.0/community/templates.mdx | 69 ++ .../contributing/developing-new-features.mdx | 34 + .../contributing/documenting.mdx | 34 + .../contributing/fixing-bugs.mdx | 29 + .../setting-up-a-dev-environment.mdx | 30 + .../contributing/ways-of-contributing.mdx | 18 + .../gettingstarted/_category_.json | 4 + .../gettingstarted/building.mdx | 22 + .../gettingstarted/development.mdx | 16 + .../gettingstarted/firstproject.mdx | 130 +++ .../gettingstarted/installation.mdx | 89 ++ .../version-v2.8.0/guides/_category_.json | 4 + .../version-v2.8.0/guides/angular.mdx | 14 + .../guides/application-development.mdx | 215 +++++ .../guides/crossplatform-build.mdx | 66 ++ .../guides/custom-protocol-schemes.mdx | 204 ++++ .../version-v2.8.0/guides/dynamic-assets.mdx | 136 +++ .../guides/file-association.mdx | 244 +++++ .../version-v2.8.0/guides/frameless.mdx | 87 ++ .../version-v2.8.0/guides/frontend.mdx | 72 ++ .../version-v2.8.0/guides/ides.mdx | 127 +++ .../guides/linux-distro-support.mdx | 103 +++ .../version-v2.8.0/guides/linux.mdx | 18 + .../guides/local-development.mdx | 55 ++ .../version-v2.8.0/guides/mac-appstore.mdx | 97 ++ .../version-v2.8.0/guides/manual-builds.mdx | 95 ++ .../version-v2.8.0/guides/migrating.mdx | 193 ++++ .../version-v2.8.0/guides/mouse-buttons.mdx | 25 + .../version-v2.8.0/guides/obfuscated.mdx | 40 + .../version-v2.8.0/guides/overscroll.mdx | 10 + .../version-v2.8.0/guides/routing.mdx | 47 + .../version-v2.8.0/guides/signing.mdx | 387 ++++++++ .../guides/single-instance-lock.mdx | 81 ++ .../version-v2.8.0/guides/sveltekit.mdx | 153 +++ .../version-v2.8.0/guides/templates.mdx | 97 ++ .../version-v2.8.0/guides/troubleshooting.mdx | 368 ++++++++ .../version-v2.8.0/guides/vscode.mdx | 82 ++ .../guides/windows-installer.mdx | 58 ++ .../version-v2.8.0/guides/windows.mdx | 61 ++ .../version-v2.8.0/howdoesitwork.mdx | 369 ++++++++ .../version-v2.8.0/introduction.mdx | 75 ++ .../version-v2.8.0/reference/_category_.json | 4 + .../version-v2.8.0/reference/cli.mdx | 240 +++++ .../version-v2.8.0/reference/menus.mdx | 230 +++++ .../version-v2.8.0/reference/options.mdx | 869 ++++++++++++++++++ .../reference/project-config.mdx | 104 +++ .../reference/runtime/_category_.json | 4 + .../reference/runtime/browser.mdx | 13 + .../reference/runtime/clipboard.mdx | 23 + .../reference/runtime/dialog.mdx | 302 ++++++ .../reference/runtime/events.mdx | 37 + .../reference/runtime/intro.mdx | 85 ++ .../version-v2.8.0/reference/runtime/log.mdx | 130 +++ .../version-v2.8.0/reference/runtime/menu.mdx | 25 + .../reference/runtime/screen.mdx | 38 + .../reference/runtime/window.mdx | 227 +++++ .../version-v2.8.0/tutorials/_category_.json | 4 + .../version-v2.8.0/tutorials/dogsapi.mdx | 245 +++++ .../version-v2.8.0/tutorials/helloworld.mdx | 123 +++ website/src/pages/changelog.mdx | 2 + .../version-v2.8.0/appendix/_category_.json | 4 + .../version-v2.8.0/community/_category_.json | 4 + .../community/links.mdx | 0 .../community/showcase/_category_.json | 4 + .../community/showcase/bulletinboard.mdx | 10 + .../community/showcase/cfntracker.mdx | 0 .../community/showcase/emailit.mdx | 10 + .../community/showcase/encrypteasy.mdx | 0 .../community/showcase/espstudio.mdx | 0 .../community/showcase/filehound.mdx | 0 .../community/showcase/hiposter.mdx | 0 .../community/showcase/minecraftupdater.mdx | 0 .../community/showcase/modalfilemanager.mdx | 0 .../community/showcase/mollywallet.mdx | 0 .../community/showcase/october.mdx | 14 + .../community/showcase/optimus.mdx | 0 .../community/showcase/portfall.mdx | 0 .../community/showcase/restic-browser.mdx | 12 + .../community/showcase/riftshare.mdx | 21 + .../community/showcase/scriptbar.mdx | 10 + .../community/showcase/snippetexpander.mdx | 27 + .../community/showcase/surge.mdx | 10 + .../community/showcase/tinyrdm.mdx | 11 + .../community/showcase/wally.mdx | 10 + .../community/showcase/warmine.mdx | 0 .../community/showcase/wombat.mdx | 0 .../version-v2.8.0/community/showcase/ytd.mdx | 10 + .../community/templates.mdx | 7 +- .../gettingstarted/_category_.json | 4 + .../gettingstarted/building.mdx | 0 .../gettingstarted/development.mdx | 0 .../gettingstarted/firstproject.mdx | 0 .../gettingstarted/installation.mdx | 6 +- .../version-v2.8.0/guides/_category_.json | 4 + .../guides/angular.mdx | 0 .../guides/application-development.mdx | 59 ++ .../guides/crossplatform-build.mdx | 65 ++ .../guides/custom-protocol-schemes.mdx | 189 ++++ .../guides/dynamic-assets.mdx | 0 .../guides/file-association.mdx | 228 +++++ .../guides/frameless.mdx | 0 .../guides/frontend.mdx | 0 .../guides/ides.mdx | 0 .../guides/linux-distro-support.mdx | 0 .../guides/linux.mdx | 0 .../guides/local-development.mdx | 0 .../guides/mac-appstore.mdx | 0 .../guides/manual-builds.mdx | 0 .../guides/migrating.mdx | 0 .../guides/mouse-buttons.mdx | 0 .../guides/obfuscated.mdx | 0 .../guides/overscroll.mdx | 0 .../version-v2.8.0/guides/routing.mdx | 47 + .../guides/signing.mdx | 27 +- .../guides/single-instance-lock.mdx | 80 ++ .../guides/sveltekit.mdx | 3 + .../guides/templates.mdx | 0 .../guides/troubleshooting.mdx | 183 +++- .../guides/vscode.mdx | 0 .../guides/windows-installer.mdx | 15 +- .../guides/windows.mdx | 0 .../howdoesitwork.mdx | 51 + .../introduction.mdx | 2 +- .../version-v2.8.0/reference/_category_.json | 4 + .../reference/cli.mdx | 67 +- .../reference/menus.mdx | 0 .../reference/options.mdx | 145 ++- .../reference/project-config.mdx | 130 +++ .../reference/runtime/_category_.json | 4 + .../reference/runtime/browser.mdx | 0 .../reference/runtime/clipboard.mdx | 0 .../reference/runtime/dialog.mdx | 0 .../reference/runtime/events.mdx | 0 .../reference/runtime/intro.mdx | 0 .../reference/runtime/log.mdx | 0 .../reference/runtime/menu.mdx | 0 .../reference/runtime/screen.mdx | 0 .../reference/runtime/window.mdx | 0 .../version-v2.8.0/tutorials/_category_.json | 4 + .../tutorials/dogsapi.mdx | 0 .../tutorials/helloworld.mdx | 0 ...bars.json => version-v2.8.0-sidebars.json} | 0 website/versions.json | 2 +- 539 files changed, 42744 insertions(+), 70 deletions(-) create mode 100644 website/i18n/en/docusaurus-plugin-content-docs/version-v2.8.0.json create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0}/guides/routing.mdx (100%) create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx create mode 100644 website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0}/appendix/_category_.json (100%) rename website/{versioned_docs/version-v2.6.0 => i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0}/community/_category_.json (100%) create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0}/community/showcase/_category_.json (100%) create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0}/gettingstarted/_category_.json (100%) create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0}/guides/_category_.json (100%) create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0}/reference/_category_.json (100%) create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0}/reference/runtime/_category_.json (100%) create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0}/tutorials/_category_.json (100%) create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx create mode 100644 website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0}/community/showcase/bulletinboard.mdx (100%) create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0}/community/showcase/emailit.mdx (100%) create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0}/community/showcase/october.mdx (100%) create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0}/community/showcase/restic-browser.mdx (100%) rename website/{versioned_docs/version-v2.6.0 => i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0}/community/showcase/riftshare.mdx (100%) rename website/{versioned_docs/version-v2.6.0 => i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0}/community/showcase/scriptbar.mdx (100%) rename website/{versioned_docs/version-v2.6.0 => i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0}/community/showcase/surge.mdx (100%) create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0}/community/showcase/wally.mdx (100%) create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0}/community/showcase/ytd.mdx (100%) create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx rename website/{versioned_docs/version-v2.6.0 => i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0}/reference/project-config.mdx (100%) create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx create mode 100644 website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx create mode 100644 website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx create mode 100644 website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/appendix/_category_.json create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/_category_.json create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/_category_.json create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/developing-new-features.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/documenting.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/fixing-bugs.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/setting-up-a-dev-environment.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/ways-of-contributing.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/_category_.json create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/_category_.json create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/_category_.json create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/_category_.json create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/_category_.json create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx create mode 100644 website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx create mode 100644 website/versioned_docs/version-v2.8.0/appendix/_category_.json create mode 100644 website/versioned_docs/version-v2.8.0/community/_category_.json rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/links.mdx (100%) create mode 100644 website/versioned_docs/version-v2.8.0/community/showcase/_category_.json create mode 100644 website/versioned_docs/version-v2.8.0/community/showcase/bulletinboard.mdx rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/showcase/cfntracker.mdx (100%) create mode 100644 website/versioned_docs/version-v2.8.0/community/showcase/emailit.mdx rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/showcase/encrypteasy.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/showcase/espstudio.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/showcase/filehound.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/showcase/hiposter.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/showcase/minecraftupdater.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/showcase/modalfilemanager.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/showcase/mollywallet.mdx (100%) create mode 100644 website/versioned_docs/version-v2.8.0/community/showcase/october.mdx rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/showcase/optimus.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/showcase/portfall.mdx (100%) create mode 100644 website/versioned_docs/version-v2.8.0/community/showcase/restic-browser.mdx create mode 100644 website/versioned_docs/version-v2.8.0/community/showcase/riftshare.mdx create mode 100644 website/versioned_docs/version-v2.8.0/community/showcase/scriptbar.mdx create mode 100644 website/versioned_docs/version-v2.8.0/community/showcase/snippetexpander.mdx create mode 100644 website/versioned_docs/version-v2.8.0/community/showcase/surge.mdx create mode 100644 website/versioned_docs/version-v2.8.0/community/showcase/tinyrdm.mdx create mode 100644 website/versioned_docs/version-v2.8.0/community/showcase/wally.mdx rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/showcase/warmine.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/showcase/wombat.mdx (100%) create mode 100644 website/versioned_docs/version-v2.8.0/community/showcase/ytd.mdx rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/community/templates.mdx (92%) create mode 100644 website/versioned_docs/version-v2.8.0/gettingstarted/_category_.json rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/gettingstarted/building.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/gettingstarted/development.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/gettingstarted/firstproject.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/gettingstarted/installation.mdx (96%) create mode 100644 website/versioned_docs/version-v2.8.0/guides/_category_.json rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/angular.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/application-development.mdx (87%) create mode 100644 website/versioned_docs/version-v2.8.0/guides/crossplatform-build.mdx create mode 100644 website/versioned_docs/version-v2.8.0/guides/custom-protocol-schemes.mdx rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/dynamic-assets.mdx (100%) create mode 100644 website/versioned_docs/version-v2.8.0/guides/file-association.mdx rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/frameless.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/frontend.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/ides.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/linux-distro-support.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/linux.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/local-development.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/mac-appstore.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/manual-builds.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/migrating.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/mouse-buttons.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/obfuscated.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/overscroll.mdx (100%) create mode 100644 website/versioned_docs/version-v2.8.0/guides/routing.mdx rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/signing.mdx (94%) create mode 100644 website/versioned_docs/version-v2.8.0/guides/single-instance-lock.mdx rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/sveltekit.mdx (98%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/templates.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/troubleshooting.mdx (55%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/vscode.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/windows-installer.mdx (79%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/guides/windows.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/howdoesitwork.mdx (93%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/introduction.mdx (97%) create mode 100644 website/versioned_docs/version-v2.8.0/reference/_category_.json rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/reference/cli.mdx (78%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/reference/menus.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/reference/options.mdx (88%) create mode 100644 website/versioned_docs/version-v2.8.0/reference/project-config.mdx create mode 100644 website/versioned_docs/version-v2.8.0/reference/runtime/_category_.json rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/reference/runtime/browser.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/reference/runtime/clipboard.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/reference/runtime/dialog.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/reference/runtime/events.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/reference/runtime/intro.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/reference/runtime/log.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/reference/runtime/menu.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/reference/runtime/screen.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/reference/runtime/window.mdx (100%) create mode 100644 website/versioned_docs/version-v2.8.0/tutorials/_category_.json rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/tutorials/dogsapi.mdx (100%) rename website/versioned_docs/{version-v2.6.0 => version-v2.8.0}/tutorials/helloworld.mdx (100%) rename website/versioned_sidebars/{version-v2.6.0-sidebars.json => version-v2.8.0-sidebars.json} (100%) diff --git a/v2/cmd/wails/internal/version.txt b/v2/cmd/wails/internal/version.txt index afe8e01d5ba..4c83680fa4d 100644 --- a/v2/cmd/wails/internal/version.txt +++ b/v2/cmd/wails/internal/version.txt @@ -1 +1 @@ -v2.7.1 \ No newline at end of file +v2.8.0 \ No newline at end of file diff --git a/website/i18n/en/docusaurus-plugin-content-docs/version-v2.8.0.json b/website/i18n/en/docusaurus-plugin-content-docs/version-v2.8.0.json new file mode 100644 index 00000000000..2e0aa803374 --- /dev/null +++ b/website/i18n/en/docusaurus-plugin-content-docs/version-v2.8.0.json @@ -0,0 +1,38 @@ +{ + "version.label": { + "message": "v2.8.0", + "description": "The label for version v2.8.0" + }, + "sidebar.docs.category.Getting Started": { + "message": "Getting Started", + "description": "The label for category Getting Started in sidebar docs" + }, + "sidebar.docs.category.Reference": { + "message": "Reference", + "description": "The label for category Reference in sidebar docs" + }, + "sidebar.docs.category.Runtime": { + "message": "Runtime", + "description": "The label for category Runtime in sidebar docs" + }, + "sidebar.docs.category.Community": { + "message": "Community", + "description": "The label for category Community in sidebar docs" + }, + "sidebar.docs.category.Showcase": { + "message": "Showcase", + "description": "The label for category Showcase in sidebar docs" + }, + "sidebar.docs.category.Guides": { + "message": "Guides", + "description": "The label for category Guides in sidebar docs" + }, + "sidebar.docs.category.Tutorials": { + "message": "Tutorials", + "description": "The label for category Tutorials in sidebar docs" + }, + "sidebar.docs.link.Contributing": { + "message": "Contributing", + "description": "The label for link Contributing in sidebar docs, linking to /community-guide#ways-of-contributing" + } +} diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx new file mode 100644 index 00000000000..d6b742435e4 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 2 +--- + +# Liens + +Cette page sert de liste pour les liens liés à la communauté. Veuillez soumettre une PR (cliquez sur `Modifier cette page` en bas) pour soumettre des liens. + +## Awesome Wails + +La [liste définitive](https://github.com/wailsapp/awesome-wails) de liens relatifs à Wails. + +## Canaux de support + +- [Serveur Discord Wails](https://discord.gg/JDdSxwjhGf) +- [Github Issues](https://github.com/wailsapp/wails/issues) +- [canal de discussion sur la bêta v2](https://github.com/wailsapp/wails/discussions/828) + +## Réseaux sociaux + +- [Twitter](https://twitter.com/wailsapp) +- [Groupe QQ pour la communauté chinoise de Wails](https://qm.qq.com/cgi-bin/qm/qr?k=PmIURne5hFGNd7QWzW5qd6FV-INEjNJv&jump_from=webapi) - Numéro de groupe : 1067173054 + +## Autres tutoriels et articles + +- [Construction d'un Panneau d'Affichage](https://blog.customct.com/building-bulletin-board) diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx new file mode 100644 index 00000000000..2c56a2e836c --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx @@ -0,0 +1,10 @@ +# BulletinBoard + +```mdx-code-block +

+ +
+

+``` + +L'application [BulletinBoard](https://github.com/raguay/BulletinBoard) est un panneau de messages versitaux pour les messages statiques ou les boîtes de dialogue pour obtenir des informations de l'utilisateur pour un script. Il a une TUI pour créer de nouvelles boîtes de dialogue qui peuvent être utilisées pour obtenir des informations de l'utilisateur. Son design est de rester en fonctionnement sur votre système et de montrer les informations au besoin, puis de se cacher. J'ai un processus pour surveiller un fichier sur mon système et pour envoyer le contenu à BulletinBoard une fois modifié. Cela fonctionne très bien avec mes workflows. Il y a auss un [workflow Alfred](https://github.com/raguay/MyAlfred/blob/master/Alfred%205/EmailIt.alfredworkflow) pour envoyer les informations au programme. Le workflow fonctionne aussi avec [EmailIt](https://github.com/raguay/EmailIt). diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..568c964b70e --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx @@ -0,0 +1,42 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Suivez les +matchs en direct de n'importe quel profil Street Fighter 6 ou V CFN. Consultez +[le site Web](https://cfn.williamsjokvist.se/) pour commencer. + +## Caractéristiques + +- Suivi des matchs en temps réel +- Stockage des journaux de match et des statistiques +- Prise en charge de l'affichage des statistiques en direct sur OBS via la + source du navigateur +- Prise en charge de SF6 et SFV +- Possibilité pour les utilisateurs de créer leurs propres thèmes de navigateur + OBS avec CSS + +### Technologie majeure utilisée aux côtés de Wails + +- [Tâche](https://github.com/go-task/task) - encapsulation de la CLI Wails pour + rendre les commandes courantes faciles à utiliser +- [React](https://github.com/facebook/react) - choisi pour son riche écosystème + (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - utilisé pour sa résolution rapide des + dépendances et son temps de construction +- [Rod](https://github.com/go-rod/rod) - automatisation du navigateur sans tête + pour les modifications d'authentification et d'interrogation +- [SQLite](https://github.com/mattn/go-sqlite3) - utilisé pour stocker les + correspondances, les sessions et les profils +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + un flux http pour envoyer des mises à jour de suivi aux sources du navigateur + OBS +- [i18next](https://github.com/i18next/) - avec connecteur backend pour servir + les objets de localisation de la couche Go +- [xstate](https://github.com/statelyai/xstate) - machines à états pour le + processus d'authentification et le suivi diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx new file mode 100644 index 00000000000..ac64e25acce --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx @@ -0,0 +1,10 @@ +# EmailIt + +```mdx-code-block +

+ +
+

+``` + +[EmailIt](https://github.com/raguay/EmailIt/) est un programme Wails 2 qui est un expéditeur de courrier électronique basé sur le markdown uniquement avec neuf blocs-notes, pour manipuler le texte et les modèles. Il a également un terminal pour exécuter des scripts dans EmailIt sur les fichiers de votre système. Les scripts et modèles peuvent être utilisés depuis la ligne de commande elle-même ou avec les extensions Alfred, Keyboard Maestro, Dropzone ou PopClip. Il supporte également les scripts et thèmes téléchargés sous GitHub. La documentation n'est pas complète, mais le programme fonctionne. Il est construit en utilisant Wails2 et Svelte, et le téléchargement est une application macOS universelle. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx new file mode 100644 index 00000000000..7f4bd7a634a --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx @@ -0,0 +1,12 @@ +# EncryptEasy + +```mdx-code-block +

+ +
+

+``` + +**[EncryptEasy](https://www.encrypteasy.app) est un outil de chiffrement PGP simple et facile à utiliser, qui gère toutes vos clés et celles de vos contacts. Le chiffrement devrait être simple. Développé avec Wails.** + +Chiffrer les messages à l'aide de PGP est la norme de l'industrie. Tout le monde a une clé privée et publique. Votre clé privée, eh bien, doit être privée afin que vous seul puissiez lire les messages. Votre clé publique est distribuée à toute personne qui veut vous envoyer des messages secrets, chiffrés. Gérer les clés, chiffrer les messages et déchiffrer les messages devrait être une expérience agréable. EncryptEasy a pour but de vous simplifier la tâche. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx new file mode 100644 index 00000000000..aae652e2c3c --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx @@ -0,0 +1,13 @@ +# ESP Studio + +```mdx-code-block +

+ +
+

+``` + +[ESP Studio](https://github.com/torabian/esp-studio) - Logiciels multiplateformes, de bureau, cloud et embarqués +pour contrôler les appareils ESP/Arduino et créer des flux de travail et des systèmes de contrôle IOT complexes \ No newline at end of file diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx new file mode 100644 index 00000000000..7522afa6ecf --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx @@ -0,0 +1,16 @@ +# Utilitaire d'exportation FileHound + +```mdx-code-block +

+ +
+

+``` + +[L'utilitaire d'exportation FileHound](https://www.filehound.co.uk/) est une plate-forme de gestion de documents cloud conçue pour la conservation sécurisée de fichiers, l'automatisation des processus métier et les capacités de SmartCapture. + +L'utilitaire d'exportation FileHound permet aux administrateurs FileHound d'exécuter des tâches sécurisées d'extraction de documents et de données à des fins alternatives de sauvegarde et de récupération. Cette application téléchargera tous les documents et/ou métadonnées enregistrés dans FileHound en fonction des filtres que vous avez choisis. Les métadonnées seront exportées dans les formats JSON et XML. + +Backend construit avec: Go 1.15 Wails 1.11.0 go-sqlite3 1.14.6 go-linq 3.2 + +Frontend avec: Vue 2.6.11 Vuex 3.4.0 TypeScript Tailwind 1.9.6 diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx new file mode 100644 index 00000000000..21fd4b11743 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx @@ -0,0 +1,10 @@ +# hiposter + +```mdx-code-block +

+ +
+

+``` + +[hiposter](https://github.com/obity/hiposter) est un outil client de test d'API http simple et efficace. Basé sur les Wails, Go et sveltejs. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx new file mode 100644 index 00000000000..5966e75fa63 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx @@ -0,0 +1,14 @@ +# Minecraft Updater + +```mdx-code-block +

+ +
+

+``` + +[Minecraft Updater](https://github.com/Gurkengewuerz/MinecraftModUpdater) est un outil utilitaire pour mettre à jour et synchroniser les mods Minecraft pour votre base d'utilisateurs. Il a été conçu en utilisant Wails2 et React avec [antd](https://ant.design/) comme framework frontend. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx new file mode 100644 index 00000000000..fe644bd7bb5 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx @@ -0,0 +1,14 @@ +# Modal File Manager + +```mdx-code-block +

+ +
+

+``` + +[Modal File Manager](https://github.com/raguay/ModalFileManager) est un gestionnaire de fichiers à double volet utilisant des technologies web. Mon design original était basé sur NW.js et peut être trouvé [ici](https://github.com/raguay/ModalFileManager-NWjs). Cette version utilise le même code frontend basé sur Svelte (mais il a été grandement modifié depuis le départ de NW.js), mais le backend est une implémentation de [Wails 2](https://wails.io/). En utilisant cette implémentation, je n'utilise plus la ligne de commande `rm`, `cp`, etc. , mais une installation de git doit être présente sur le système pour télécharger des thèmes et des extensions. Il est entièrement codé en utilisant Go et fonctionne beaucoup plus rapidement que les versions précédentes. + +Ce gestionnaire de fichiers est conçu autour du même principe que Vim: l'état est contrôlé par des actions via le clavier. Le nombre d'états n'est pas fixe, mais très programmable. Par conséquent, un nombre infini de configurations de clavier qui peuvent être créées et utilisées. C'est la principale différence par rapport aux autres gestionnaires de fichiers. Il y a des thèmes et des extensions disponibles à télécharger à partir de GitHub. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx new file mode 100644 index 00000000000..70a6cd1f44d --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx @@ -0,0 +1,10 @@ +# Molley Wallet + +```mdx-code-block +

+ +
+

+``` + +[Molly Wallet](https://github.com/grvlle/constellation_wallet/) le portefeuille officiel $DAG du Constellation Network. Cela permettra aux utilisateurs d'interagir avec le réseau Hypergraph de différentes manières, sans se limiter à la production de transactions en $DAG. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx new file mode 100644 index 00000000000..5a9789d8711 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx @@ -0,0 +1,14 @@ +# October + +```mdx-code-block +

+ +
+

+``` + +[Octobre](https://october.utf9k.net) est une petite application Wails qui rend vraiment facile d'extraire les surlignements de [Kobo eReaders](https://en.wikipedia.org/wiki/Kobo_eReader) puis de les transférer vers [Readwise](https://readwise.io). + +Il a une taille relativement petite avec toutes les versions de la plate-forme pesant en moins de 10 Mo, et c'est sans activer la [compression UPX](https://upx.github.io/)! + +En revanche, les précédentes tentatives de l'auteur avec Electron ont rapidement gonflé à plusieurs centaines de mégaoctets. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx new file mode 100644 index 00000000000..41744234d37 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx @@ -0,0 +1,10 @@ +# Optimus + +```mdx-code-block +

+ +
+

+``` + +[Optimus](https://github.com/splode/optimus) est une application d'optimisation d'image de bureau. Il supporte la conversion et la compression entre les formats d’images WebP, JPEG et PNG. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx new file mode 100644 index 00000000000..acdc682becf --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx @@ -0,0 +1,10 @@ +# Portfall + +```mdx-code-block +

+ +
+

+``` + +[Portfall](https://github.com/rekon-oss/portfall) - Un portail de redirection de port k8 pour un accès facile à toutes les interfaces de votre instance diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx new file mode 100644 index 00000000000..b6597166852 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx @@ -0,0 +1,12 @@ +# Restic Browser + +```mdx-code-block +

+ +
+

+``` + +[Restic-Browser](https://github.com/emuell/restic-browser) - Une interface de sauvegarde simple et multiplateforme [restic](https://github.com/restic/restic) pour la navigation et la restauration de dépôts restic. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx new file mode 100644 index 00000000000..e47b2397e63 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx @@ -0,0 +1,21 @@ +# RiftShare + +```mdx-code-block +

+ +
+

+``` + +Partage de fichiers facile, sécurisé et gratuit pour tout le monde. Apprenez-en plus sur [Riftshare.app](https://riftshare.app) + +## Fonctionnalités + +- Partage facile et sécurisé de fichiers entre ordinateurs à la fois sur le réseau local et via Internet +- Supporte l'envoi de fichiers ou de répertoires de manière sécurisée par le protocole [magic wormhole](https://magic-wormhole.readthedocs.io/en/latest/) +- Compatible avec toutes les autres applications utilisant magic wormhole (magic-wormhole or wormhole-william CLI, wormhole-gui, etc.) +- Compression automatique de plusieurs fichiers sélectionnés à envoyer en même temps +- Animations complètes, barre de progression et support d'annulation pour l'envoi et la réception +- Sélection de fichier natif au système d'exploitation +- Ouvrir les fichiers en un seul clic une fois reçus +- Mise à jour automatique - ne vous inquiétez pas d'avoir la dernière version! diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx new file mode 100644 index 00000000000..d7215d66126 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx @@ -0,0 +1,10 @@ +# ScriptBar + +```mdx-code-block +

+ +
+

+``` + +[ScriptBar](https://GitHub.com/raguay/ScriptBarApp) est un programme pour afficher la sortie de scripts ou d'un serveur [Node-Red](https://nodered.org). Il exécute des scripts définis dans le programme EmailIt et affiche la sortie. Des scripts de xBar ou TextBar peuvent être utilisés. Actuellement sur les scripts TextBar fonctionnent bien. Il affiche également la sortie des scripts sur votre système. ScriptBar ne les met pas dans la barre de menus, mais les a tous dans une fenêtre convenable pour une visualisation facile. Vous pouvez avoir plusieurs onglets pour voir plusieurs choses différentes. Vous pouvez également conserver les liens vers vos sites Web les plus visités. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx new file mode 100644 index 00000000000..b5917484303 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx @@ -0,0 +1,10 @@ +# Surge + +```mdx-code-block +

+ +
+

+``` + +[Surge](https://getsurge.io/) est une application de partage de fichiers p2p conçue pour utiliser les technologies blockchain afin d'activer les transferts de fichiers 100 % anonymes. Surge est chiffré de bout en bout, décentralisé et open source. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx new file mode 100644 index 00000000000..e3124bab727 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx @@ -0,0 +1,11 @@ +# Tiny RDM + +```mdx-code-block +

+ + +
+

+``` + +The [Tiny RDM](https://redis.tinycraft.cc/) application is an open-source, modern lightweight Redis GUI. It has a beautful UI, intuitive Redis database management, and compatible with Windows, Mac, and Linux. It provides visual key-value data operations, supports various data decoding and viewing options, built-in console for executing commands, slow log queries and more. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx new file mode 100644 index 00000000000..ba2a7fccc45 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx @@ -0,0 +1,10 @@ +# Wally + +```mdx-code-block +

+ +
+

+``` + +[Wally](https://ergodox-ez.com/pages/wally) est le flasheur officiel du firmware pour les claviers [Ergodox](https://ergodox-ez.com/). C'est un excellent exemple de ce que vous pouvez réaliser avec Wails : la capacité de combiner la puissance de Go et les riches outils graphiques du monde du développement web. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx new file mode 100644 index 00000000000..2e427433069 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx @@ -0,0 +1,19 @@ +# Lanceur Minecraft pour WarMine + +```mdx-code-block +

+ + +
+

+``` + +[Lanceur Minecraft pour WarMine](https://warmine.ru/) est une application Wails qui vous permet facilement de rejoindre le serveur de jeu contenant les mods, ainsi que la gestion de vos comptes de jeu. + +Le Launcher télécharge les fichiers du jeu, vérifie leur intégrité et lance le jeu avec une large gamme d'options de personnalisation. + +Le frontend est écrit en Svelte, le lanceur entier tient dans 9Mo et prend en charge Windows 7-11. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx new file mode 100644 index 00000000000..c431f691952 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx @@ -0,0 +1,10 @@ +# Wombat + +```mdx-code-block +

+ +
+

+``` + +[Wombat](https://github.com/rogchap/wombat) est un client gRPC multi-plateforme. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx new file mode 100644 index 00000000000..4f5bd993cb1 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx @@ -0,0 +1,10 @@ +# Ytd + +```mdx-code-block +

+ +
+

+``` + +[Ytd](https://github.com/marcio199226/ytd/tree/v2-wails) est une application pour télécharger des pistes depuis youtube, créer des listes de lecture hors ligne et les partager avec vos amis, vos amis seront en mesure de lire vos playlists ou de les télécharger pour l'écoute hors ligne, a un lecteur intégré. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx new file mode 100644 index 00000000000..6baf0941b8c --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx @@ -0,0 +1,69 @@ +--- +sidebar_position: 1 +--- + +# Modèles + +Cette page sert de liste pour les modèles supportés par la communauté. Veuillez soumettre une PR (cliquez sur `Modifier cette page` en bas) pour inclure vos modèles. Pour construire votre propre modèle, veuillez consulter le guide [Modèles](../guides/templates.mdx). + +Pour utiliser ces modèles, exécutez `wails init -n "Votre nom de projet" -t [le lien ci-dessous[@version]]` + +S'il n'y a pas de suffixe de version, la branche principale du modèle de code sera alors utilisé par défaut. S'il y a un suffixe de version, le modèle de code correspondant au tag de cette version sera utilisé. + +Exemple : `wails init -n "Votre nom de projet" -t https://github.com/misitebao/wails-template-vue` + +:::warning Attention + +**Le projet Wails n'entretient pas, et n'est pas responsable des modèles de tierces parties!** + +Si vous n'êtes pas sûr d'un modèle, inspectez `package.json` et `wails.json` pour savoir quels scripts sont exécutés et quels paquets sont installés. + +::: + +## Vue + +- [wails-template-vue](https://github.com/misitebao/wails-template-vue) - Modèle de Wails basé sur Vue (TypeScript intégré, thème sombre, internationalisation, routage de page unique, TailwindCSS) +- [wails-vite-vue-ts](https://github.com/codydbentley/wails-vite-vue-ts) - Vue 3 TypeScript avec Vite (et instructions pour ajouter des fonctionnalités) +- [wails-vite-vue-the-works](https://github.com/codydbentley/wails-vite-vue-the-works) - Vue 3 TypeScript avec Vite, Vuex, Vue Router, Sass, et ESLint + Prettier +- [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - Un modèle utilisant JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier) +- [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - Un modèle utilisant TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier, Composition API avec <script setup>) +- [wails-template-naive](https://github.com/tk103331/wails-template-naive) - Modèle Wails basé sur Naive UI (Librairie de composants Vue 3) + +## Angular + +- [wails-template-angular](https://github.com/mateothegreat/wails-template-angular) - Modèle Angular 15+ prêt à être utilisé en production. +- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - Angular avec TypeScript, Sass, rechargement à chaud, découpage dynamique de code et i18n + +## React + +- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - Un modèle utilisant reactjs +- [wails-react-template](https://github.com/flin7/wails-react-template) - Un modèle minimal pour React qui supporte le développement en direct +- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - Un modèle utilisant Next.js et TypeScript +- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - Un modèle pour React + TypeScript + Vite + TailwindCSS +- [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - Un modèle avec Vite, React, TypeScript, TailwindCSS, et shadcn/ui + +## Svelte + +- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - Un modèle utilisant Svelte +- [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - Un modèle utilisant Svelte et Vite +- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - Un modèle utilisant Svelte et Vite avec TailwindCSS v3 +- [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - Un modèle mis à jour en utilisant Svelte v4.2.0 et Vite avec TailwindCSS v3.3.3 +- [wails-sveltekit-template](https://github.com/h8gi/wails-sveltekit-template) - Un modèle utilisant SvelteKit + +## Solid + +- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-ts) - Un modèle utilisant Solid + Ts + Vite +- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-js) - Un modèle utilisant Solid + Js + Vite + +## Elm + +- [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - Développez votre application GUI avec de la programmation fonctionnelle et une configuration de développement en direct :tada: :rocket: +- [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - Combine les puissances :muscle: d'Elm + Tailwind CSS + Wails ! Rechargement automatique pris en charge. + +## HTMX + +- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - Utilisez une combinaison unique de htmx pour interactivité, et de templ pour créer des composants et des formes + +## Pure JavaScript (Vanilla) + +- [wails-pure-js-template](https://github.com/KiddoV/wails-pure-js-template) - Un modèle avec rien que du JavaScript, du HTML et du CSS de base diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx new file mode 100644 index 00000000000..eb43f4aae2c --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx @@ -0,0 +1,22 @@ +--- +sidebar_position: 6 +--- + +# Compiler votre projet + +À partir du répertoire du projet, exécutez `wails build`. Cela compilera votre projet et sauvegardera le binaire prêt à la production dans le répertoire `build/bin`. + +Si vous exécutez le binaire, vous devriez voir l'application par défaut : + +```mdx-code-block +
+ +
+
+``` + +Pour plus de détails sur les options de compilation, veuillez vous référer à la [documentation du CLI](../reference/cli.mdx#build). diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx new file mode 100644 index 00000000000..307029141d4 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx @@ -0,0 +1,16 @@ +--- +sidebar_position: 5 +--- + +# Développez votre application + +Vous pouvez exécuter votre application en mode développement en exécutant `wails dev` à partir du répertoire de votre projet. Cela fera les choses suivantes : + +- Construire votre application et l'exécuter +- Lier votre code Go au frontend pour qu'il puisse être appelé à partir de JavaScript +- En utilisant la puissance de [Vite](https://vitejs.dev/), surveillera les modifications dans vos fichiers Go et reconstruira / ré-exécutera en cas de changement +- Mettra en place un [serveur web](http://localhost:34115) qui servira votre application via un navigateur. Cela vous permet d'utiliser les extensions de votre navigateur préféré. Vous pouvez même appeler votre code Go depuis la console + +Pour commencer, exécutez `wails dev` dans le répertoire du projet. Plus d'informations à ce sujet peuvent être trouvées [ici](../reference/cli.mdx#dev). + +Prochainement : Tutoriel diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx new file mode 100644 index 00000000000..383925af1e6 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 2 +--- + +# Créer un projet + +## Génération de projet + +Maintenant que le CLI est installé, vous pouvez générer un nouveau projet en utilisant la commande `wails init`. + +Choisissez votre framework favori : + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + Générer un projet Svelte utilisant JavaScript avec:

+ + wails init -n myproject -t svelte + +Si vous préférez utiliser TypeScript:
+ + wails init -n myproject -t svelte-ts + +
+ + Générer un projet React utilisant JavaScript avec :

+ + wails init -n myproject -t react + +Si vous préférez utiliser TypeScript:
+ + wails init -n myproject -t react-ts + +
+ + Générer un projet Vue utilisant JavaScript avec:

+ + wails init -n myproject -t vue + +Si vous préférez TypeScript:
+ + wails init -n myproject -t vue-ts + +
+ + Générer un projet Preact utilisant JavaScript avec:

+ + wails init -n myproject -t preact + +Si vous préférez TypeScript:
+ + wails init -n myproject -t preact-ts + +
+ + Générer un projet Lit utilisant JavaScript avec:

+ + wails init -n myproject -t lit + +Si vous préférez TypeScript:
+ + wails init -n myproject -t lit-ts + +
+ + Générer un projet Vanilla utilisant JavaScript avec :

+ + wails init -n myproject -t vanilla + +Si vous préférez TypeScript:
+ + wails init -n myproject -t vanilla-ts + +
+
+``` + +
+ +Il y a aussi [des modèles créés par la communauté](../community/templates.mdx) qui sont disponibles et qui offrent différentes possibilités. + +Pour voir les autres options disponibles, vous pouvez exécuter `wails init -help`. Plus de détails peuvent être trouvés dans la [documentation du CLI](../reference/cli.mdx#init). + +## Structure du projet + +Les projets Wails ont la structure suivante: + +``` +. +├── build/ +│ ├── appicon.png +│ ├── darwin/ +│ └── windows/ +├── frontend/ +├── go.mod +├── go.sum +├── main.go +└── wails.json +``` + +### Récapitulatif de la structure du projet + +- `/main.go` - L'application principale +- `/frontend/` - Fichiers de la partie frontend +- `/build/` - Répertoire de construction du projet +- `/build/appicon.png` - L'icône de l'application +- `/build/darwin/` - Fichiers spécifiques pour Mac +- `/build/windows/` - Fichiers spécifiques pour Windows +- `/wails.json` - La configuration du projet +- `/go.mod` - Le fichier du module Go +- `/go.sum` - Le checksum du fichier du module Go + +Le répertoire `frontend` n'a rien de spécifique à Wails et n'importe quel outil de frontend peut être utilisé. + +Le répertoire `build` est utilisé pendant le processus de compilation. Ces fichiers peuvent être mis à jour pour personnaliser vos builds. Si fichiers sont supprimés du répertoire de compilation, les versions par défaut seront régénérées. + +Le nom du module par défaut dans `go.mod` est "changeme". Vous devriez changer cela pour quelque chose de plus approprié. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx new file mode 100644 index 00000000000..86ffde34bde --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx @@ -0,0 +1,90 @@ +--- +sidebar_position: 1 +--- + +# Installation + +## Plates-formes Prises en charge + +- Windows 10/11 AMD64/ARM64 +- MacOS 10.13+ AMD64 +- MacOS 11.0+ ARM64 +- Linux AMD64/ARM64 + +## Dépendances + +Wails a un certain nombre de dépendances communes qui sont nécessaires avant l'installation : + +- Go 1.18+ +- NPM (Node 15+) + +### Go + +Télécharger Go à partir de la [Page de téléchargement](https://go.dev/dl/). + +Assurez-vous que vous suivez les instructions officielles de [l'installation de Go](https://go.dev/doc/install). Vous devrez également vous assurer que votre variable d'environnement `PATH` inclut également le chemin vers votre répertoire `~/go/bin`. Redémarrez votre terminal et effectuez les vérifications suivantes : + +- Vérifiez que Go est installé correctement : `go version` +- Vérifiez que "~/go/bin" est dans votre variable PATH : `echo $PATH | grep go/bin` + +### NPM + +Téléchargez le NPM à partir de la [page de téléchargement de Node](https://nodejs.org/en/download/). Il est préférable d'utiliser la dernière version car c'est avec celle-là que nous effectuons nos tests. + +Exécutez `npm --version` pour vérifier. + +## Dépendances spécifiques aux plateformes + +Vous devrez également installer des dépendances spécifiques liés à la plateforme que vous utilisez : + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + Wails a besoin que les outils de command line xocde soient installés. Cela peut être fait + en exécutant xcode-select --install. + + + Wails a besoin que WebView2 runtime soit installé. Certaines installations de Windows auront déjà installé cette fonctionnalité. Vous pouvez vérifier en utilisant la commande wails doctor. + + + Linux a besoin de gcc comme outil de compilation en plus de libgtk3 et libwebkit. Plutôt que de lister une tonne de commandes pour différentes distributions, Wails peut essayer de déterminer ce que sont les commandes d'installation pour votre distribution. Exécutez wails doctor après l'installation pour voir de quelles dépendances vous avez besoin. Si votre gestionnaire de distribution/paquet n'est pas pris en charge, veuillez consulter le guide Ajouter une distribution Linux. + + +``` + +## Dépendances optionnelles + +- [UPX](https://upx.github.io/) pour compresser vos applications. +- [NSIS](https://wails.io/docs/guides/windows-installer/) pour générer des installateurs Windows. + +## Installer Wails + +Exécutez `go go install github.com/wailsapp/wails/v2/cmd/wails@latest` pour installer le CLI. + +Note: Si vous obtenez une erreur similaire à ceci: + +```shell +....\Go\pkg\mod\github.com\wailsapp\wails\v2@v2.1.0\pkg\templates\templates.go:28:12: pattern all:ides/*: no matching files found +``` +vérifiez que vous avez installé Go 1.18+ : +```shell +go version +``` + +## Vérification du système + +Exécuter `wails doctor` qui vérifiera si vous avez les bonnes dépendances installées. Si ce n'est pas le cas, il vous conseillera sur ce qui manque et vous aidera à corriger tout problème. + +## La commande `wails` semble manquer ? + +Si votre système signale que la commande `wails` est manquante, assurez-vous que vous avez suivi le guide d'installation correctement. Normalement, cela signifie que le répertoire `go/bin` du répertoire racine de votre utilisateur n'est pas dans la variable d'environnement `PATH` . Vous devrez également normalement fermer et réouvrir toutes les commandes ouvertes afin que les modifications apportées à l'environnement par l'installateur soient reflétées dans l'invite de commande. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx new file mode 100644 index 00000000000..1fe2f199ffe --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx @@ -0,0 +1,14 @@ +# Angular + +Bien que Wails n'ait pas de modèle Angular, il est possible d'utiliser Angular avec Wails. + +## Dev Mode + +Pour que le mode développeur fonctionne avec Angular, vous devez ajouter ce qui suit à votre fichier `wails.json`: + +```json + "frontend:build": "npx ng build", + "frontend:install": "npm install", + "frontend:dev:watcher": "npx ng serve", + "frontend:dev:serverUrl": "http://localhost:4200", +``` \ No newline at end of file diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx new file mode 100644 index 00000000000..411853fd6f1 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx @@ -0,0 +1,215 @@ +# Développement d'applications + +Il n'y a pas de règles gravées dans le marbre pour le développement d'applications avec Wails, mais il y a quelques lignes directrices de base. + +## Configuration de l'application + +Le modèle utilisé par défaut défini que `main.go` est utilisé pour configurer et démarrer l'application, tandis que `app.go` est utilisé pour définir la logique de l'application. + +Le fichier `app.go` va définir une structure qui a 2 méthodes qui agissent comme crochets dans l'application principale: + +```go title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} +``` + +- La méthode startup est appelée d-s que Wails a donné les ressources nécessaires et qu'il est dans un bon état pour créer les ressources, mettre en place les event listeners et tout ce dont l'application peut avoir besoin pour démarrer. Il est donné un `context.Context` qui est généralement sauvegardé dans un champ struct. Ce contexte est nécessaire pour appeler le [runtime](../reference/runtime/intro.mdx). Si cette méthode renvoie une erreur, l'application se fermera. En mode développement, l'erreur sera affichée dans la console. + +- La méthode d'arrêt sera appelée par Wails à la fin du processus d'arrêt. C'est un bon endroit pour vider la mémoire et effectuer toutes les tâches d'arrêt. + +Le fichier `main.go` consiste généralement en un seul appel à `wails.Run()`, qui accepte la configuration de l'application. Le modèle utilisé par les templates fait qu'avant l'appel à `wails.Run()`, une instance du struct que l'on a définie dans `app.go` est créée et instanciée dans une variable appelée `app`. Cette configuration est l'endroit où nous ajoutons nos callbacks : + +```go {3,9,10} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +Plus d'informations sur les crochets du cycle de vie des applications peuvent être trouvées [ici](../howdoesitwork.mdx#application-lifecycle-callbacks). + +## Méthodes de liaison + +Il est probable que vous vouliez appeler les méthodes Go depuis le frontend. Cela se fait normalement en ajoutant des méthodes publiques à le struct déjà défini dans `app.go`: + +```go {16-18} title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +Dans la configuration principale de l'application, le paramètre `Bind` est l'endroit où nous pouvons dire à Wails ce que nous voulons lier : + +```go {11-13} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +Cela liera toutes les méthodes publiques de notre structure `App` (cela ne liera jamais les méthodes de démarrage et d'arrêt du système). + +### Traiter avec le contexte lors de la liaison de plusieurs structures + +Si vous voulez lier des méthodes pour des structures multiples, mais que vous voulez que chaque struct conserve une référence au contexte pour que vous puissiez utiliser les fonctions d'exécution... Un bon choix est de passer le contexte de la méthode `OnStartup` à vos instances struct : + +```go +func main() { + + app := NewApp() + otherStruct := NewOtherStruct() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: func(ctx context.Context){ + app.SetContext(ctx) + otherStruct.SetContext(ctx) + }, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + otherStruct + }, + }) + if err != nil { + log.Fatal(err) + } +} +``` + +Plus d'informations à sur Binding peuvent être trouvées [ici](../howdoesitwork.mdx#method-binding). + +## Menu de l’application + +Wails prend en charge l'ajout d'un menu à votre application. Ceci est fait en passant un [Menu](../reference/menus.mdx#menu) structuré à la configuration de l'application. Il est courant d'utiliser une méthode qui renvoie un Menu, et encore plus courant pour que cela soit une méthode sur la struct de l'`app` qui soit utilisée pour les hooks du cycle de vie. + +```go {11} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Menu: app.menu(), + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +## Ressources + +La grande chose à propos de la façon dont Wails v2 gère les ressources pour le frontend, est que ce n'est pas le cas! La seule chose que vous devez donner à Wails est un `embed.FS`. C'est à vous de décider comment vous y arrivez. Vous pouvez utiliser les fichiers html/css/js vanilla comme dans le modèle vanilla. Vous pourriez avoir un système de compilation compliqué, peu importe. + +Quand la commande `wails dev` est exécutée, elle vérifiera le fichier de projet `wails.json` à la racine du projet. Il y a 2 clés dans le fichier du projet qui sont lues : + +- "frontend:install" +- "frontend:build" + +Le premier, si fourni, sera exécuté dans le répertoire `frontend` pour installer les modules. Le second, si fourni, sera exécuté dans le répertoire `frontend` pour construire le projet frontend. + +Si ces 2 clés ne sont pas fournies, alors Wails ne fait absolument rien avec le frontend. Il n'attend que `embed.FS`. + +### AssetsHandler + +Une application Wails v2 peut éventuellement définir un `http.Handler` dans `options.app`, qui permet de se connecter à l'AssetServer pour créer des fichiers à la volée ou traiter les requêtes POST/PUT. Les requêtes GET sont toujours traitées d'abord par le `assets` FS. Si le FS ne trouve pas le fichier demandé, la requête sera transmise au `http.Handler`. Toute requête autre que GET sera traitée directement par le `AssetsHandler` si spécifié. Il est également possible d'utiliser le `AssetsHandler` uniquement en spécifiant `nil` dans l'option `Assets`. + +## Serveur de développement embarqué + +Exécuter `wails dev` démarrera le serveur de développement intégré qui démarrera un observateur de fichiers dans votre répertoire de projet. Par par défaut, si un fichier change, wails vérifie s'il s'agit d'un fichier d'application (par défaut: `.go`, configurable avec l'option `-e`). Si c'est le cas, il reconstruira votre application et la relancera. Si le fichier modifié se trouvait dans les actifs, il lancera un rechargement après un court laps de temps. + +Le serveur de développement utilise une technique appelée "debouncing", ce qui signifie qu'il ne se recharge pas tout de suite, comme il peut y avoir plusieurs fichiers modifiés en un court laps de temps. Lorsqu'un déclencheur se produit, il attend un temps défini avant d'émettre un rechargement. Si un autre déclencheur se produit, le temps d'attente se réinitialise avant un prochain rechargement. Par défaut, cette période est définie à `100ms`. Si cette valeur ne fonctionne pas pour votre projet, elle peut être configurée en utilisant l'option `-debounce`. Si elle est utilisée, cette valeur sera enregistrée dans la configuration de votre projet et deviendra la valeur par défaut. + +## Serveur de développement externe + +Certains frameworks sont fournis avec leur propre serveur de rechargement en direct, cependant ils ne seront pas en mesure de tirer parti des liaisons Wails Go. Dans ce scénario, il est préférable d'exécuter un script qui va surveiller le projet dans dossier build, dossier que Wails surveille aussi. Pour un exemple, voir le modèle svelte par défaut qui utilise [rollup](https://rollupjs.org/guide/en/). + +### Créer une application React + +Le processus pour créer un projet Reactest un peu plus compliqué. Afin de prendre en charge le rechargement du frontend en direct, la configuration suivante doit être ajoutée à votre `wails.json`: + +```json + "frontend:dev:watcher": "yarn start", + "frontend:dev:serverUrl": "http://localhost:3000", +``` + +La commande `frontend:dev:watcher` démarrera le serveur de développement React (hébergé sur le port `3000` typiquement). La commande `frontend:dev:serverUrl` demande ensuite à Wails d'exposer les ressources depuis le serveur de développement lors du chargement du frontend, plutôt que depuis le dossier de construction. En plus de ce qui précède, le fichier `index.html` doit être mis à jour avec les éléments suivants : + +```html + + + + + +``` + +Ceci est nécessaire, car la commande watcher qui reconstruit le frontend empêche Wails de les injecter. Ça contourne le problème en assurant les scripts sont toujours injectés. Avec cette configuration, `wails dev` peut être exécuté, ce qui construira le frontend et le backend de manière appropriée avec le rechargement à chaud activé. De plus, lorsque vous accédez à l'application à partir d'un navigateur, les outils de développement de React peuvent maintenant être utilisés sur une version non minifiée de l'application pour le débogage. Enfin, pour des compilations plus rapides, `wails dev -s` peut être exécuté pour passer la construction par défaut du frontend par Wails car c'est une étape inutile. + +## Module Go + +Les modèles Wails par défaut génèrent un fichier `go.mod` qui contient le nom de module "changeme". Vous devriez changer ceci pour quelque chose de plus approprié après la génération du projet. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx new file mode 100644 index 00000000000..fd81a974d04 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx @@ -0,0 +1,66 @@ +# Crossplatform build with Github Actions + +To build a Wails project for all the available platforms, you need to create an application build for each operating system. One effective method to achieve this is by utilizing GitHub Actions. + +An action that facilitates building a Wails app is available at: +https://github.com/dAppServer/wails-build-action + +In case the existing action doesn't fulfill your requirements, you can select only the necessary steps from the source: +https://github.com/dAppServer/wails-build-action/blob/main/action.yml + +Below is a comprehensive example that demonstrates building an app upon the creation of a new Git tag and subsequently uploading it to the Actions artifacts: + +```yaml +name: Wails build + +on: + push: + tags: + # Match any new tag + - '*' + +env: + # Necessary for most environments as build failure can occur due to OOM issues + NODE_OPTIONS: "--max-old-space-size=4096" + +jobs: + build: + strategy: + # Failure in one platform build won't impact the others + fail-fast: false + matrix: + build: + - name: 'App' + platform: 'linux/amd64' + os: 'ubuntu-latest' + - name: 'App' + platform: 'windows/amd64' + os: 'windows-latest' + - name: 'App' + platform: 'darwin/universal' + os: 'macos-latest' + + runs-on: ${{ matrix.build.os }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Build wails + uses: dAppServer/wails-build-action@v2.2 + id: build + with: + build-name: ${{ matrix.build.name }} + build-platform: ${{ matrix.build.platform }} + package: false + go-version: '1.20' +``` + +This example offers opportunities for various enhancements, including: + +- Caching dependencies +- Code signing +- Uploading to platforms like S3, Supbase, etc. +- Injecting secrets as environment variables +- Utilizing environment variables as build variables (such as version variable extracted from the current Git tag) diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx new file mode 100644 index 00000000000..e86b651845d --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx @@ -0,0 +1,204 @@ +# Custom Protocol Scheme association + +Custom Protocols feature allows you to associate specific custom protocol with your app so that when users open links with this protocol, +your app is launched to handle them. This can be particularly useful to connect your desktop app with your web app. +In this guide, we'll walk through the steps to implement custom protocols in Wails app. + +## Set Up Custom Protocol Schemes Association: + +To set up custom protocol, you need to modify your application's wails.json file. +In "info" section add a "protocols" section specifying the protocols your app should be associated with. + +For example: + +```json +{ + "info": { + "protocols": [ + { + "scheme": "myapp", + "description": "My App Protocol", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------ | +| scheme | Custom Protocol scheme. e.g. myapp | +| description | Windows-only. The description. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open custom protocol with your app, the system will launch your app and call the `OnUrlOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnUrlOpen: func(url string) { println(url) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows Custom Protocol Schemes is supported only with NSIS installer. During installation, the installer will create a +registry entry for your schemes. When you open url with your app, new instance of app is launched and url is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there (note that `%u` is important in Exec). Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=x-scheme-handler/myapp; +``` + +2. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +``` + +3. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with custom protocol scheme. When you open url with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx new file mode 100644 index 00000000000..97f81432dc2 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx @@ -0,0 +1,136 @@ +# Ressources dynamiques + +Si vous voulez charger ou générer des ressources pour votre frontend de manière dynamique, vous pouvez y parvenir en utilisant l'option [AssetsHandler](../reference/options#assetshandler). Le AssetsHandler est un générique`http.Handler` qui sera appelé pour toute requête non GET sur le serveur d'assets et pour les requêtes GET qui ne peuvent pas être servies car l'asset n'est pas trouvé. + +En installant un AssetsHandler personnalisé, vous pouvez servir vos propres ressources en utilisant un serveur de ressources personnalisé. + +## Exemple + +Dans notre exemple de projet, nous allons créer un gestionnaire de ressources simple qui chargera les fichiers à partir du disque: + +```go title=main.go {17-36,49} +package main + +import ( + "embed" + "fmt" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "net/http" + "os" + "strings" +) + +//go:embed all:frontend/dist +var assets embed.FS + +type FileLoader struct { + http.Handler +} + +func NewFileLoader() *FileLoader { + return &FileLoader{} +} + +func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) { + var err error + requestedFilename := strings.TrimPrefix(req.URL.Path, "/") + println("Requesting file:", requestedFilename) + fileData, err := os.ReadFile(requestedFilename) + if err != nil { + res.WriteHeader(http.StatusBadRequest) + res.Write([]byte(fmt.Sprintf("Could not load file %s", requestedFilename))) + } + + res.Write(fileData) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "helloworld", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: NewFileLoader(), + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 255}, + OnStartup: app.startup, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +Lorsque nous exécutons l'application en mode dev en utilisant `wails dev`, nous verrons la sortie suivante : + +``` +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' failed, using AssetHandler +Requesting file: favicon.ico +``` + +Comme vous pouvez le voir, le gestionnaire d'actifs est appelé lorsque le serveur d'assets par défaut est incapable de servir le fichier `favicon.ico`. + +Si vous faites un clic droit sur l'application principale et sélectionnez "inspecter" pour afficher les devtools, vous pouvez tester cette fonctionnalité en tapant ce qui suit dans la console : + +``` +let response = await fetch('does-not-exist.txt'); +``` + +Cela générera une erreur dans les devtools. Nous pouvons voir que l'erreur est ce que nous attendons est retourné par notre gestionnaire de ressources personnalisées : + +```mdx-code-block +

+ +

+``` + +Cependant, si nous demandons `go.mod`, nous verrons la sortie suivante : + +```mdx-code-block +

+ +

+``` + +Cette technique peut être utilisée pour charger des images directement dans la page. Si nous avons mis à jour notre modèle vanilla par défaut et a remplacé l'image du logo : + +```html + +``` + +avec : + +```html + +``` + +Nous verrions ensuite ce qui suit: + +```mdx-code-block +

+ +

+``` + +:::warning + +Exposer votre système de fichiers de cette manière est un risque de sécurité. Il est recommandé de gérer correctement l'accès à votre système de fichiers. + +::: diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx new file mode 100644 index 00000000000..167955b12d7 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx @@ -0,0 +1,244 @@ +# File Association + +File association feature allows you to associate specific file types with your app so that when users open those files, +your app is launched to handle them. This can be particularly useful for text editors, image viewers, or any application +that works with specific file formats. In this guide, we'll walk through the steps to implement file association in Wails app. + +## Set Up File Association: + +To set up file association, you need to modify your application's wails.json file. +In "info" section add a "fileAssociations" section specifying the file types your app should be associated with. + +For example: + +```json +{ + "info": { + "fileAssociations": [ + { + "ext": "wails", + "name": "Wails", + "description": "Wails Application File", + "iconName": "wailsFileIcon", + "role": "Editor" + }, + { + "ext": "jpg", + "name": "JPEG", + "description": "Image File", + "iconName": "jpegFileIcon", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | +| ext | The extension (minus the leading period). e.g. png | +| name | The name. e.g. PNG File | +| iconName | The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows | +| description | Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open file (or files) with your app, the system will launch your app and call the `OnFileOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnFileOpen: func(filePaths []string) { println(filestring) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows file association is supported only with NSIS installer. During installation, the installer will create a +registry entry for your file associations. When you open file with your app, new instance of app is launched and file path is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there. Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=application/x-wails;application/x-test +``` + +2. Create mime types file. Example: + +```xml + + + + Wails Application File + + + +``` + +3. Create icons for your file types. SVG icons are recommended. +4. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload mime types to register file associations +update-mime-database /usr/share/mime +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +# update icons +update-icon-caches /usr/share/icons/* +``` + +5. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ./application-wails-mime.xml + dst: /usr/share/mime/packages/application-x-wails.xml +- src: ./application-test-mime.xml + dst: /usr/share/mime/packages/application-x-test.xml +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with specified file types. When you open file with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx new file mode 100644 index 00000000000..bbeb338f1b6 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx @@ -0,0 +1,87 @@ +# Applications sans cadre + +Wails prend en charge la création d'applications qui n'ont pas de cadres. Ceci peut être réalisé en utilisant le champ [frameless](../reference/options.mdx#frameless) dans [Application Options](../reference/options.mdx#application-options). + +Wails offre une solution simple pour faire glisser la fenêtre: N'importe quel élément HTML qui a le style CSS `--wails-draggable:drag` agira comme une "poignée de glisser". Cette propriété s'applique à tous les éléments enfants. Si vous devez indiquer qu'un élément imbriqué ne doit pas glisser, alors utilisez l'attribut '--wails-draggable:no-drag' sur cet élément. + +```html + + + + + + + +
+ + +
+
+ + + + +``` + +Pour certains projets, l'utilisation d'une variable CSS peut ne pas être possible en raison du style dynamique. Dans ce cas, vous pouvez utiliser les options `CSSDragProperty` et `CSSDragValue` pour définir une propriété et une valeur qui seront utilisées pour indiquer régions glissables : + +```go title=main.go +package main + +import ( + "embed" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "alwaysontop", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Frameless: true, + CSSDragProperty: "widows", + CSSDragValue: "1", + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +```html title=index.html + + + + + + alwaysontop + + +
+ + + +``` + +:::info Plein écran + +Si vous autorisez votre application à être en plein écran, cette fonctionnalité de glissement sera désactivée. + +::: diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx new file mode 100644 index 00000000000..ea101019ad8 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx @@ -0,0 +1,72 @@ +# Frontend + +## Injection de script + +Quand Wails sert votre fichier `index.html`, par défaut, il injectera 2 entrées de script dans la balise `` pour charger `/wails/ipc.js` et `/wails/runtime.js`. Ces fichiers installent respectivement les bindings et les runtime. + +Le code ci-dessous montre où ils sont injectés par défaut : + +```html + + + injection example + + + + + + + +
Please enter your name below 👇
+
+ + +
+ + + + +``` + +### Remplacer l'injection de script par défaut + +Pour fournir plus de flexibilité aux développeurs, il y a une balise meta qui peut être utilisée pour personnaliser ce comportement: + +```html + +``` + +Les options sont les suivantes : + +| Valeur | Description | +| ------------------- | -------------------------------------------------------------- | +| noautoinjectruntime | Pour désactiver l'injection automatique de `/wails/runtime.js` | +| noautoinjectipc | Pour désactiver l'injection automatique de `/wails/ipc.js` | +| noautoinject | Pour désactiver l'injection automatique de tous les scripts | + +Plusieurs options peuvent être utilisées à condition qu'elles soient séparées par des virgules. + +Ce code est parfaitement valide et fonctionne de la même manière que la version avec l'auto-injection : + +```html + + + injection example + + + + + + +
Please enter your name below 👇
+
+ + +
+ + + + + + +``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx new file mode 100644 index 00000000000..f35b2f57f77 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx @@ -0,0 +1,127 @@ +# IDEs + +Wails vise à fournir une grande expérience de développement. À cet effet, nous supportons maintenant la génération d'une configuration spécifique IDE pour fournir une configuration plus souple du projet. + +Actuellement, nous prenons en charge [Visual Studio Code](https://code.visualstudio.com/) mais nous visons à prendre en charge d'autres IDE comme Goland. + +## Visual Studio Code + +```mdx-code-block +

+ +

+``` + +Lors de la génération d'un projet en utilisant l'option `-ide vscode` , les fichiers IDE seront créés à côté des autres fichiers du projet. Ces fichiers sont placés dans le répertoire `.vscode` et fournissent la configuration correcte pour déboguer votre application. + +Les 2 fichiers générés sont `tasks.json` et `launch.json`. Ci-dessous se trouvent les fichiers générés par défaut : + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/myproject.exe" + ] + } + ] +} +``` + +```json title="launch.json" +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Wails: Debug myproject", + "type": "go", + "request": "launch", + "mode": "exec", + "program": "${workspaceFolder}/build/bin/myproject.exe", + "preLaunchTask": "build", + "cwd": "${workspaceFolder}", + "env": {} + } + ] +} +``` + +### Configuration des étapes d'installation et de construction + +Le fichier `tasks.json` est simple pour le projet par défaut car il n'y a pas d'étapes `npm install` ou `npm build` nécessaire. Pour les projets qui ont une étape de construction en frontend comme avec Svelte, nous devrions modifier `tasks.json` pour ajouter les étapes d'installation et de construction suivantes : + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "npm install", + "type": "npm", + "script": "install", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "npm run build", + "type": "npm", + "script": "build", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/vscode.exe" + ], + "dependsOn": ["npm install", "npm run build"] + } + ] +} +``` + +:::info Améliorations futures + +Dans le futur, nous espérons générer un `tasks.json` qui inclut les étapes d'installation et de construction automatiquement. + +::: diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx new file mode 100644 index 00000000000..6bd2002fce7 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx @@ -0,0 +1,103 @@ +# Prise en charge des distributions Linux + +## Vue d'ensemble + +Wails offre le support de Linux, mais fournir des instructions d'installation pour toutes les distributions disponibles est une tâche impossible. À la place, Wails essaie de déterminer si les paquets dont vous avez besoin pour développer des applications sont disponibles via le gestionnaire de paquets de votre système. Actuellement, nous supportons les gestionnaires de paquets suivants : + +- apt +- dnf +- emerge +- eopkg +- nixpkgs +- pacman +- zypper + +## Ajout des noms de paquets + +Il peut y avoir des cas où votre distribution de linux utilise un des gestionnaires de paquets pris en charge mais le nom du paquet est différent. Par exemple, vous pouvez utiliser un dérivé Ubuntu, mais le nom du paquet pour gtk peut être différent. Wails tente de trouver le paquet correct en itérant une liste de noms de paquets. La liste des paquets est stockée dans un fichier spécifique dans le dossier `v2/internal/system/packagemanager` . Dans notre exemple, ce serait `v2/internal/system/packagemanager/apt.go`. + +Dans ce fichier, la liste des paquets est définie par la méthode `Packages()`: + +```go +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +Supposons que dans notre distribution linux, `libgtk-3` est empaqueté sous le nom `lib-gtk3-dev`. Nous pourrions ajouter le support de ce paquet en ajoutant la ligne suivante : + +```go {5} +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + {Name: "lib-gtk3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +## Ajout de nouveaux gestionnaires de paquets + +Pour ajouter un nouveau gestionnaire de paquets, effectuez les étapes suivantes : + +- Créez un nouveau fichier dans `v2/internal/system/packagemanager` appelé `.go`, où `` est le nom du gestionnaire de paquets. +- Définit une structure conforme à l'interface du gestionnaire de paquets définie dans `pm.go`: + +```go +type PackageManager interface { + Name() string + Packages() packagemap + PackageInstalled(*Package) (bool, error) + PackageAvailable(*Package) (bool, error) + InstallCommand(*Package) string +} +``` + +- `Name()` doit retourner le nom du gestionnaire de paquets +- `Packages()` doit retourner une `packagemap`, qui fournit des noms de fichiers candidats pour les dépendances +- `PackageInstalled()` devrait retourner `true` si le paquet donné est installé +- `PackageAvailable()` devrait retourner `true` si le paquet donné n'est pas installé mais disponible pour l'installation +- `InstallCommand()` doit retourner la commande exacte pour installer le nom du paquet donné + +Jetez un coup d'œil au code des autres gestionnaires de paquets pour avoir une idée de comment cela fonctionne. + +:::info Rappel + +Si vous ajoutez le support d'un nouveau gestionnaire de paquets, n'oubliez pas de mettre également à jour cette page ! + +::: diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx new file mode 100644 index 00000000000..19e45313a44 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx @@ -0,0 +1,18 @@ +# Linux + +Cette page a divers guides liés au développement d'applications Wails pour Linux. + +## Le tag vidéo ne déclenche pas l'événement "terminé" + +Lorsque vous utilisez un tag vidéo, l'événement "terminé" n'est pas déclenché lorsque la vidéo est finie. Ceci est un bogue dans WebkitGTK, cependant vous pouvez utiliser le contournement suivant pour le corriger : + +```js +videoTag.addEventListener("timeupdate", (event) => { + if (event.target.duration - event.target.currentTime < 0.2) { + let ended = new Event("ended"); + event.target.dispatchEvent(ended); + } +}); +``` + +Source : [Lyimmi](https://github.com/Lyimmi) sur le [forum de discussion](https://github.com/wailsapp/wails/issues/1729#issuecomment-1212291275) diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx new file mode 100644 index 00000000000..0c3878d7888 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx @@ -0,0 +1,55 @@ +# Développement local + +## Vue d'ensemble + +Wails est en développement constant et les nouvelles versions sont régulièrement "tagguées". Cela se produit généralement lorsque tout le nouveau code sur `master` a été testé et confirmé fonctionnel. Si vous avez besoin d'un correctif ou d'une fonctionnalité qui ne l'a pas encore fait pour une version, il est possible d'utiliser la dernière version "non validée" en utilisant les étapes suivantes : + +- `git clone https://github.com/wailsapp/wails` +- `cd wails/v2/cmd/wails` +- `go install` + +REMARQUE : Le répertoire dans lequel vous avez cloné le projet sera maintenant appelé "clonedir". + +Le CLI de Wails sera maintenant à la dernière version. + +### Mise à jour du projet + +Pour mettre à jour vos projets pour utiliser la dernière version de la bibliothèque Wails, mettez à jour le fichier `go.mod` et assurez-vous que la ligne suivante est en bas du fichier : + +`replace github.com/wailsapp/wails/v2 => ` + +Exemple: + +Sur Windows: `replace github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2` + +Sur 'nix: `replace github.com/wailsapp/wails/v2 => /home/me/projects/wails/v2` + +Pour revenir à une version stable, exécutez : + +`go install github.com/wailsapp/wails/v2/cmd/wails@latest` + +## Tester une branche + +Si vous voulez tester une branche, suivez les instructions ci-dessus, mais assurez-vous de bien vous mettre sur la branche que vous voulez tester avant d'installer : + +- `git clone https://github.com/wailsapp/wails` +- `cd wails` +- `git checkout -b branch-to-test --track origin/branch-to-test` +- `cd v2/cmd/wails` +- `go install` + +Assurez-vous de [mettre à jour votre projet](#updating-your-project) comme décrit ci-dessus. + +## Tester une PR + +Si vous voulez tester une PR, suivez les instructions ci-dessus, mais assurez-vous de récupérer la PR et d'être sur la branche de la PR avant de faire l'installation. Veuillez remplacer `[IDofThePR]` par l'ID de la PR affiché sur github.com: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails` +- `git fetch -u origin pull/[IDofThePR]/head:test/pr-[IDofThePR]` +- `git checkout test/pr-[IDofThePR]` +- `git reset --hard HEAD` +- `cd v2/cmd/wails` +- `go install` + +Assurez-vous de [mettre à jour votre projet](#updating-your-project) comme décrit ci-dessus. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx new file mode 100644 index 00000000000..fe040591634 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx @@ -0,0 +1,97 @@ +# Guide pour Mac App Store + +Cette page donne un bref aperçu de la façon de soumettre votre application Wails au Mac App Store. + +## Prérequis + +- Vous devrez avoir un compte développeur Apple. Veuillez trouver plus d'informations sur le site [Apple Developer Program](https://developer.apple.com/support/compare-memberships/) +- Vous aurez besoin que vos certificats, identifiants et applications soient créés sur le portail développeur. Plus d'infos sur ce sujet ci-dessous +- L'utilitaire Xcode devront être installés sur votre machine locale pour être utilisé en ligne de commandes + +#### Créer des certificats et des identifiants + +1. Allez sur votre [Compte Développeur Apple](https://developer.apple.com/account/) +2. Sous `Certificats, Identificateurs & Profils`, cliquez sur `Identifiants` et Enregistrez un nouvel identifiant d'application. Utiliser le format (com.example.app) +3. Sous la même page, cliquez sur `Certificats` et générez de nouveaux certificats pour la distribution de l'App Store Mac. Téléchargez-les et importez les certificats dans votre trousseau sur votre machine locale. + +#### Créer une soumission d'application + +1. Allez sur le [site de connexion de l'App Store](https://appstoreconnect.apple.com/apps) +2. Enregistrez une nouvelle application et liez l'ID du lot que vous avez créé à l'étape précédente +3. Remplissez votre application avec les bonnes captures d'écran, descriptions, etc. selon les besoins d'Apple +4. Créer une nouvelle version de votre application + +#### Create Provisioning Profile +1. Go to the [Apple Developer Profiles](https://developer.apple.com/account/resources/profiles/list) page +2. Add a new provisioning profile for Mac App Store Distribution +3. Set the Profile Type as Mac and select the App ID for the application created above +4. Select the Mac App Distribution certificate +5. Name the Provisioning Profile embedded and download the created profile. + +## Processus Mac App Store + +#### Activation du Sandbox Apple + +Les applications soumises au Mac App Store doivent tourner dans la [Sandbox](https://developer.apple.com/app-sandboxing/) Apple. Vous devez créer un fichier `entitlements.plist` pour que cela fonctionne. La recommandation est de créer ce fichier sous ce chemin `{PROJECT_DIR}/build/darwin/entitlements.plist`. + +**Example de fichier Entitlements** + +Ceci est un exemple du fichier entitlements de l'application [RiftShare](https://github.com/achhabra2/riftshare). Pour référence, veuillez mettre dans les droits requis par votre application. Reportez-vous à [ce site](https://developer.apple.com/documentation/bundleresources/entitlements) pour plus d'informations. You will need to replace the Team ID and Application Name with the ones you registered above. + +```xml title="entitlements.plist" + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + com.apple.application-identifier + TEAM_ID.APP_NAME + com.apple.developer.team-identifier + TEAM_ID + + +``` + +**Add the Embedded Provisioning Profile** The Provisioning Profile created above needs to be added to the root of the applicaton. It needs to be named embedded.provisionprofile. + +#### Construire et signer le package de l'application + +Ce qui suit est un exemple de script pour construire et signer votre application pour la soumission de l'App Store Mac. Il suppose que vous exécutez le script depuis la racine de votre projet. + +Notez que les certificats pour signer l'application et l'installateur sont différents. Veuillez vous assurer que les deux sont importés dans votre trousseau. Trouvez les chaînes de caractères dans Trousseau et insérez-les ci-dessous. Remplissez le nom de votre certificat et le nom de l'application ci-dessous. Exécuter le script suivant générera un fichier `app.pkg` signé à la racine de votre application. + +```bash title="macappstore-build.sh" +#!/bin/bash + +APP_CERTIFICATE="3rd Party Mac Developer Application: YOUR NAME (CODE)" +PKG_CERTIFICATE="3rd Party Mac Developer Installer: YOUR NAME (CODE)" +APP_NAME="YourApp" + +wails build -platform darwin/universal -clean + +cp ./embedded.provisionprofile "./build/bin/$APP_NAME.app/Contents" + +codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist ./build/bin/$APP_NAME.app + +productbuild --sign "$PKG_CERTIFICATE" --component ./build/bin/$APP_NAME.app /Applications ./$APP_NAME.pkg +``` + +#### Télécharger l'application + +Vous devrez télécharger le fichier de package généré et l'associer à votre application avant de pouvoir le soumettre pour vérification. + +1. Téléchargez l' [App Transporter](https://apps.apple.com/us/app/transporter/id1450874784) depuis le Mac App Store +2. Ouvrez-le et connectez-vous avec votre identifiant Apple +3. Cliquez sur le signe + et sélectionnez le fichier `APP_NAME.pkg` que vous avez généré à l'étape précédente. Télécharger le +4. Retournez sur le site [App Store Connect](https://appstoreconnect.apple.com/apps) et retournez dans la soumission de votre application. Sélectionnez la version que vous êtes prêt à mettre à disposition sur l'App Store. Sous `Build` sélectionnez le package que vous avez téléchargé via Transporter. + +C'est terminé ! Vous pouvez maintenant utiliser le site pour soumettre votre application pour vérification. Après quelques jours ouvrables si tout se passe bien, vous devriez voir votre application en direct sur le Mac App Store. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx new file mode 100644 index 00000000000..98457d19cc9 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx @@ -0,0 +1,95 @@ +# Compilations manuelles + +Le CLI Wails fait beaucoup de travail pour le projet, mais il est parfois souhaitable de construire manuellement votre projet. Ce document discutera des différentes opérations que fait le CLI et des différentes façons d'y parvenir. + +## Processus de construction + +Lorsque `wails build` ou `wails dev` sont utilisés, le CLI Wails effectue un processus de construction commun: + + - Installation des dépendances frontend + - Construire le projet frontend + - Générer des ressources de construction + - Compiler l'application + - [optionnel] Compresser l'application + +### Installation des dépendances frontend + +#### Étapes CLI + +- Si l'option `-s` est donné, cette étape est ignorée +- Vérifie `wails.json` pour voir s'il y a une commande install dans `frontend:install` +- S'il n'y en a pas, il saute cette étape +- Si le fichier existe, vérifie si `package.json` existe dans le répertoire du frontend. S'il n'existe pas, il saute cette étape +- Un hash MD5 est générée à partir du contenu du fichier `package.json` +- Il vérifie l'existence de `package.json.md5` et, s'il existe, compare son contenu (une somme MD5) avec celui généré pour voir si le contenu a changé. S'ils sont les mêmes, cette étape est ignorée +- Si `package.json.md5` n'existe pas, il le crée en utilisant la somme MD5 générée +- Si une compilation est maintenant requise, ou si `node_modules` n'existe pas, ou si l'option `-f` est donnée, la commande install est exécutée dans le répertoire frontend + +#### Étapes manuelles + +Cette étape peut être réalisée à partir de la ligne de commande ou d'un script avec `npm install`. + +### Construire le projet frontend + +#### CLI Wails + +- Si l'option `-s` est donné, cette étape est ignorée +- Vérifie `wails.json` pour voir s'il y a une commande de construction dans la clé `frontend:build` +- S'il n'y en a pas, il saute cette étape +- S'il existe, il est exécuté dans le répertoire du frontend + +#### Étapes manuelles + +Cette étape peut être réalisée à partir de la ligne de commande ou d'un script avec `npm run build` ou quel que soit le script de construction du frontend. + +### Générer les ressources + +#### CLI Wails + +- Si l'option `-nopackage` est activée, cette étape est ignorée +- Si le fichier `build/appicon.png` n'existe pas, un fichier par défaut est créé +- Pour Windows, voir [ Empaquetage pour Windows](#windows) +- Si `build/windows/icon.ico` n'existe pas, il la créera à partir de l'image `build/appicon.png`. + +##### Windows + +- If `build/windows/icon.ico` does not exist, it will create it from `build/appicon.png` using icon sizes of 256, 128, 64, 48, 32 and 16. This is done using [winicon](https://github.com/leaanthony/winicon). +- If the `build/windows/.manifest` file does not exist, it creates it from a default version. +- Compiles the application as a production build (above) +- Uses [winres](https://github.com/tc-hib/winres) to bundle the icon and manifest into a `.syso` file ready for linking. + +#### Étapes manuelles + +- Create `icon.ico` using the [winicon](https://github.com/leaanthony/winicon) CLI tool (or any other tool). +- Create / Update a `.manifest` file for your application +- Use the [winres CLI](https://github.com/tc-hib/go-winres) to generate a `.syso` file. + +### Compiler l'application + +#### CLI Wails + +- If the `-clean` flag is provided, the `build` directory is deleted and recreated +- For `wails dev`, the following default Go flags are used: `-tags dev -gcflags "all=-N -l"` +- For `wails build`, the following default Go flags are used: `-tags desktop,production -ldflags "-w -s"` + - On Windows, `-ldflags "-w -h -H windowsgui"` +- Additional tags passed to the CLI using `-tags` are added to the defaults +- Additional ldflags passed to the CLI using `-ldflags` are added to the defaults +- The `-o` flag is passed through +- The Go compiler specified by `-compiler` will be used for compilation + +#### Manual steps + +- For dev build, the minimum command would be: `go build -tags dev -gcflags "all=-N -l"` +- For production build, the minimum command would be: `go build -tags desktop,production -ldflags "-w -s -H windowsgui"` +- Ensure that you compile in the same directory as the `.syso` file + +### Compress application + +#### CLI Wails + +- If the `-upx` flag has been given, the `upx` program will be run to compress the application with the default settings +- If `-upxflags` is also passed, these flags are used instead of the default ones + +#### Manual steps + +- Run `upx [flags]` manually to compress the application. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx new file mode 100644 index 00000000000..7123cbe6b60 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx @@ -0,0 +1,191 @@ +# Migrating from v1 + +## Overview + +Wails v2 is a significant change from v1. This document aims to highlight the changes and the steps in migrating an existing project. + +### Creating the Application + +In v1, the main application is created using `wails.CreateApp`, bindings are added with `app.Bind`, then the application is run using `app.Run()`. + +Example: + +```go title="v1" + app := wails.CreateApp(&wails.AppConfig{ + Title: "MyApp", + Width: 1024, + Height: 768, + JS: js, + CSS: css, + Colour: "#131313", + }) + app.Bind(basic) + app.Run() +``` + +In v2, there is just a single method, `wails.Run()`, that accepts [application options](../reference/options.mdx#application-options). + +```go title="v2" + err := wails.Run(&options.App{ + Title: "MyApp", + Width: 800, + Height: 600, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + basic, + }, + }) +``` + +### Binding + +In v1, it was possible to bind both arbitrary functions and structs. In v2, this has been simplified to only binding structs. The struct instances that were previously passed to the `Bind()` method in v1, are now specified in the `Bind` field of the [application options](../reference/options.mdx#application-options): + +```go title="v1" + app := wails.CreateApp(/* options */) + app.Bind(basic) +``` + +```go title="v2" + err := wails.Run(&options.App{ + /* other options */ + Bind: []interface{}{ + basic, + }, + }) +``` + +In v1, bound methods were available to the frontend at `window.backend`. This has changed to `window.go`.`` + +### Application Lifecycle + +In v1, there were 2 special methods in a bound struct: `WailsInit()` and `WailsShutdown()`. These have been replaced with 3 lifecycle hooks as part of the [application options](../reference/options.mdx#application-options): + +- [OnStartup](../reference/options.mdx#onstartup) +- [OnShutdown](../reference/options.mdx#onshutdown) +- [OnDomReady](../reference/options.mdx#ondomready) + +Note: [OnDomReady](../reference/options.mdx#ondomready) replaces the `wails:ready` system event in v1. + +These methods can be standard functions, but a common practice is to have them part of a struct: + +```go title="v2" + basic := NewBasicApp() + err := wails.Run(&options.App{ + /* Other Options */ + OnStartup: basic.startup, + OnShutdown: basic.shutdown, + OnDomReady: basic.domready, + }) +... +type Basic struct { + ctx context.Context +} +func (b *Basic) startup(ctx context.Context) { + b.ctx = ctx +} +... +``` + +### Runtime + +The runtime in v2 is much richer than v1 with support for menus, window manipulation and better dialogs. The signature of the methods has changed slightly - please refer the the [Runtime Reference](../reference/runtime/intro.mdx). + +In v1, the [runtime](../reference/runtime/intro.mdx) was available via a struct passed to `WailsInit()`. In v2, the runtime has been moved out to its own package. Each method in the runtime takes the `context.Context` that is passed to the [OnStartup](../reference/options.mdx#onstartup) method. + +```go title="Runtime Example" +package main + +import "github.com/wailsapp/wails/v2/pkg/runtime" + +type Basic struct { + ctx context.Context +} + +// startup is called at application startup +func (a *App) startup(ctx context.Context) { + a.ctx = ctx + runtime.LogInfo(ctx, "Application Startup called!") +} + +``` + +### Assets + +The _biggest_ change in v2 is how assets are handled. + +In v1, assets were passed via 2 application options: + +- `JS` - The application's JavaScript +- `CSS` - The application's CSS + +This meant that the responsibility of generating a single JS and CSS file was on the developer. This essentially required the use of complicated packers such as webpack. + +In v2, Wails makes no assumptions about your frontend assets, just like a webserver. All of your application assets are passed to the application options as an `embed.FS`. + +**This means there is no requirement to bundle your assets, encode images as Base64 or attempt the dark art of bundler configuration to use custom fonts**. + +At startup, Wails will scan the given `embed.FS` for `index.html` and use its location as the root path for all the other application assets - just like a webserver would. + +Example: An application has the following project layout. All final assets are placed in the `frontend/dist` directory: + +```shell +. +├── build/ +├── frontend/ +│ └── dist/ +│ ├── index.html +│ ├── main.js +│ ├── main.css +│ └── logo.svg +├── main.go +└── wails.json +``` + +Those assets may be used by the application by simply creating an `embed.FS`: + +```go title="Assets Example" +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + err := wails.Run(&options.App{ + /* Other Options */ + AssetServer: &assetserver.Options{ + Assets: assets, + }, + }) +} +``` + +Of course, bundlers can be used if you wish to. The only requirement is to pass the final application assets directory to Wails using an `embed.FS` in the `Assets` key of the [application options](../reference/options.mdx#application-options). + +### Project Configuration + +In v1, the project configuration was stored in the `project.json` file in the project root. In v2, the project configuration is stored in the `wails.json` file in the project root. + +The format of the file is slightly different. Here is a comparison: + +

+ +| v1 | v2 | Notes | +| ------------------ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | name | | +| description | | Removed | +| author / name | author / name | | +| author / email | author / email | | +| version | version | | +| binaryname | outputfilename | Changed | +| frontend / dir | | Removed | +| frontend / install | frontend:install | Changed | +| frontend / build | frontend:build | Changed | +| frontend / bridge | | Removed | +| frontend / serve | | Removed | +| tags | | Removed | +| | wailsjsdir | The directory to generate wailsjs modules | +| | assetdir | The directory of the compiled frontend assets for `dev` mode. This is normally inferred and could be left empty. | +| | reloaddirs | Comma separated list of additional directories to watch for changes and to trigger reloads in `dev` mode. This is only needed for some more advanced asset configurations. | + +

diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx new file mode 100644 index 00000000000..4a3de2a61b5 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx @@ -0,0 +1,25 @@ +# Mouse Buttons + +The Wails runtime intercepts mouse clicks to determine whether a frameless window needs resizing or a window needs to be moved. It has been asked how to detect when a mouse click has occurred, because `window.onclick` doesn't report the mouse buttons correctly. The following code shows how to detect mouse clicks: + +```javascript +window.addEventListener("mousedown", handleMouseButtonDown); + +function handleMouseButtonDown(event) { + if (event.button === 0) { + // left mouse button + } else if (event.button === 1) { + // middle mouse button + } else if (event.button === 2) { + // right mouse button + } else if (event.button === 3) { + // back mouse button + } else if (event.button === 4) { + // forward mouse button + } else { + // other mouse button + } +} +``` + +Reference: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx new file mode 100644 index 00000000000..21f7875e389 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx @@ -0,0 +1,40 @@ +# Obfuscated Builds + +Wails includes support for obfuscating your application using [garble](https://github.com/burrowers/garble). + +To produce an obfuscated build, you can use the `-obfuscate` flag with the `wails build` command: + +```bash +wails build -obfuscated +``` + +To customise the obfuscation settings, you can use the `-garbleargs` flag: + +```bash +wails build -obfuscated -garbleargs "-literals -tiny -seed=myrandomseed" +``` + +These settings may be persisted in your [project config](../reference/project-config). + +## How it works + +In a standard build, all bound methods are available in the frontend under the `window.go` variable. When these methods are called, the corresponding backend method is called using the fully qualified function name. When using an obfuscated build, methods are bound using an ID instead of a name. The bindings generated in the `wailsjs` directory use these IDs to call the backend functions. + +:::note + +To ensure that your application will work in obfuscated mode, you must use the generated bindings under the `wailsjs` directory in your application. + +::: + +## Example + +Importing the "Greet" method from the bindings like this: + +```js +import { Greet } from "../../wailsjs/go/main/App"; + +// snip +Greet("World"); +``` + +will ensure that the method will work correctly in obfuscated mode, as the bindings will be regenerated with IDs and the call mechanism updated. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx new file mode 100644 index 00000000000..9d1d772d0fb --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx @@ -0,0 +1,10 @@ +# Overscroll + +[Overscroll](https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior) is the "bounce effect" you sometimes get when you scroll beyond a page's content boundaries. This is common in mobile apps. This can be disabled using CSS: + +```css +html { + height: 100%; + overflow: hidden; +} +``` diff --git a/website/versioned_docs/version-v2.6.0/guides/routing.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/routing.mdx rename to website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx new file mode 100644 index 00000000000..4c7cf45ba99 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx @@ -0,0 +1,387 @@ +# Code Signing + +This is a guide on how you can sign your binaries generated with Wails on MacOS and Windows. The guide will target CI environments, more specifically GitHub Actions. + +## Windows + +First off you need a code signing certificate. If you do not already have one, Microsoft's info page lists some providers [here](https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/get-a-code-signing-certificate). Please note that an EV certificate is not required unless you need to write kernel-level software such as device drivers. For signing your Wails app, a standard code signing certificate will do just fine. + +It may be a good idea to check with your certificate provider how to sign your binaries on your local machine before targeting automated build systems, just so you know if there are any special requirements. For instance, [here](https://www.ssl.com/how-to/using-your-code-signing-certificate/) is SSL.com's code signing guide for Windows. If you know how to sign locally, it will be easier to troubleshoot any potential issues in a CI environment. For instance, SSL.com code signing certificates require the `/tr` flag for [SignTool.exe](https://docs.microsoft.com/en-us/windows/win32/seccrypto/signtool) while other providers may only need the `/t` flag for providing the timestamping server. Popular GitHub Actions for signing Windows binaries like [this one](https://github.com/Dana-Prajea/code-sign-action) does not support the `/tr` flag on SignTool.exe. Therefore this guide will focus on signing our app manually with PowerShell commands, but you can use actions like the [code-sign-action](https://github.com/Dana-Prajea/code-sign-action) Action if you prefer. + +First off, let's make sure we are able to build our Wails app in our GitHub CI. Here is a small workflow template: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend manually here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +Next we need to give the GitHub workflow access to our signing certificate. This is done by encoding your .pfx or .p12 certificate into a base64 string. To do this in PowerShell, you can use the following command assuming your certificate is called 'my-cert.p12': + +```PowerShell +certutil -encode .\my-cert.p12 my-cert-base64.txt +``` + +You should now have your .txt file with the base64 encoded certificate. It should start with _-----BEGIN CERTIFICATE-----_ and end with _-----END CERTIFICATE-----_. Now you need to make two action secrets on GitHub. Navigate to _Settings -> Secrets -> Actions_ and create the two following secrets: + +- **WIN_SIGNING_CERT** with the contents of your base64 encoded certificate text. +- **WIN_SIGNING_CERT_PASSWORD** with the contents of your certificate password. + +Now we're ready to implement the signing in our workflow using one of the two methods: + +### Method 1: signing with commands + +This method uses PowerShell commands to sign our app, and leaves you control over the entire signing process. + +After the `"Build Wails app"` step, we can add the following step to our workflow: + +```yaml +- name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd /t /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' + +``` + +This script creates a new directory for your certificate file, creates the certificate file from our base64 secret, converts it to a .pfx file, and finally signs the binary. The following variables needs to be replaced in the last line: + +- **signing algorithm**: usually sha256. +- **timestamping server**: URL to the timestamping server to use with your certificate. +- **path to binary**: path to the binary you want to sign. + +Given that our Wails config has `outputfilename` set to "app.exe" and that we have a certificate from SSL.com, this would be our workflow: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\app.exe + + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +### Method 2: automatically signing with Action + +It is possible to use a Windows code signing Action like [this](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate) one, but note it requires a SHA1 hash for the certificate and a certificate name. View an example of how to configure it on the Action's [marketplace](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate). + +--- + +## MacOS + +First off you need your code signing certificate from Apple. If you do not have one, a simple Google search will help you acquire one. Once you have your certificate, you need to export it and encode it to base64. [This tutorial](https://localazy.com/blog/how-to-automatically-sign-macos-apps-using-github-actions) shows you how to do that in an easy manner. Once you have exported your .p12 certificate file, you can encode it to base64 as seen in the tutorial with the following command: + +```bash +base64 Certificates.p12 | pbcopy +``` + +Now you're ready to create some GitHub project secrets, just as with Windows: + +- **APPLE_DEVELOPER_CERTIFICATE_P12_BASE64** with the contents of your newly copied base64 certificate. +- **APPLE_DEVELOPER_CERTIFICATE_PASSWORD** with the contents of your certificate password. +- **APPLE_PASSWORD** with the contents of an App-Specific password to your Apple-ID account which you can generate [here](https://appleid.apple.com/account/manage). + +Let's make sure we are able to build our Wails app in our GitHub Action workflow. Here is a small template: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +For code signing on macOS, [gon](https://github.com/mitchellh/gon) is a very handy tool for code signing and communicating with Apple servers, also written in Go, and will be used in this guide. + +After the `Build Wails app` step, add the following to the workflow: + +```yaml +- name: MacOS download gon for code signing and app notarization + if: matrix.platform == 'macos-latest' + run: | + brew install mitchellh/gon/gon +``` + +Now we need to configure some gon config files in our `build/darwin` directory: + +1. gon-sign.json: + +```json +{ + "source": ["./build/bin/app.app"], + "bundle_id": "app.myapp", + "apple_id": { + "username": "my-appleid@email.com", + "password": "@env:APPLE_PASSWORD" + }, + "sign": { + "application_identity": "Developer ID Application: My Name" + } +} +``` + +Where `source` is your Wails binary, `bundle_id` is your bundle ID, `apple_id` contains your Apple ID username and App-Specific password which you created earlier, and `sign.application_identity` is your identity which you can find by running the following command: + +```bash +security find-identity -v -p codesigning +``` + +2. entitlements.plist: + +```plist + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + + +``` + +In this file you configure the entitlements you need for you app, e.g. camera permissions if your app uses the camera. Read more about entitlements [here](https://developer.apple.com/documentation/bundleresources/entitlements). + +Make sure you have updated your `Info.plist` file with the same bundle ID as you entered in `gon-sign.json`. Here's an example `Info.plist` file: + +```plist + + + CFBundlePackageTypeAPPL + CFBundleNameMyApp + CFBundleExecutableapp + CFBundleIdentifierapp.myapp + CFBundleVersion0.1.0 + CFBundleGetInfoStringMy app is cool and nice and chill and + CFBundleShortVersionString0.1.0 + CFBundleIconFileiconfile + LSMinimumSystemVersion10.13.0 + NSHighResolutionCapabletrue + LSApplicationCategoryTypepublic.app-category.utilities + NSHumanReadableCopyright© Me + +``` + +Now we're ready to add the signing step in our workflow after building the Wails app: + +```yaml +- name: Import Code-Signing Certificates for macOS + if: matrix.platform == 'macos-latest' + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} +- name: Sign our macOS binary + if: matrix.platform == 'macos-latest' + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json +``` + +Please note that signing binaries with Apple could take anywhere from minutes to hours. + +## Combined workflow file: + +Here is our GitHub workflow file with Windows + macOS combined: + +```yaml +name: "example combined" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: MacOS download gon for code signing and app notarization + if: matrix.platform == 'macos-latest' + run: | + brew install mitchellh/gon/gon + - name: Import Code-Signing Certificates for macOS + if: matrix.platform == 'macos-latest' + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} + - name: Sign our macOS binary + if: matrix.platform == 'macos-latest' + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json + - name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\Monitor.exe + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +# End notes + +This guide inspired by the RiftShare project and its workflow, which is highly recommended to check out [here](https://github.com/achhabra2/riftshare/blob/main/.github/workflows/build.yaml). diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx new file mode 100644 index 00000000000..dc7706f8ffa --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx @@ -0,0 +1,81 @@ +# Single Instance Lock + +Single instance lock is a mechanism that allows you to prevent multiple instances of your app from running at the same time. +It is useful for apps that are designed to open files from the command line or from the OS file explorer. + +## Important + +Single Instance Lock does not implement a secure communications protocol between instances. When using single instance lock, +your app should treat any data passed to it from second instance callback as untrusted. +You should verify that args that you receive are valid and don't contain any malicious data. + +## How it works + +Windows: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via a shared window using [SendMessage](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage) +macOS: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via [NSDistributedNotificationCenter](https://developer.apple.com/documentation/foundation/nsdistributednotificationcenter) +Linux: Single instance lock is implemented using [dbus](https://www.freedesktop.org/wiki/Software/dbus/). The dbus name is generated from the unique id that you provide. Data is passed to the first instance via [dbus](https://www.freedesktop.org/wiki/Software/dbus/) + +## Usage + +When creating your app, you can enable single instance lock by passing a `SingleInstanceLock` struct to the `App` struct. +Use the `UniqueId` field to specify a unique id for your app. +This id is used to generate the mutex name on Windows and macOS and the dbus name on Linux. Use a UUID to ensure that the id is unique. +The `OnSecondInstanceLaunch` field is used to specify a callback that is called when a second instance of your app is launched. +The callback receives a `SecondInstanceData` struct that contains the command line arguments passed to the second instance and the working directory of the second instance. + +Note that OnSecondInstanceLaunch don't trigger windows focus. +You need to call `runtime.WindowUnminimise` and `runtime.Show` to bring your app to the front. +Note that on linux systems window managers may prevent your app from being brought to the front to avoid stealing focus. + +```go title="main.go" +var wailsContext *context.Context + +// NewApp creates a new App application struct +func NewApp() *App { + return &App{} +} + +// startup is called when the app starts. The context is saved +// so we can call the runtime methods +func (a *App) startup(ctx context.Context) { + wailsContext = &ctx +} + +func (a *App) onSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) { + secondInstanceArgs = secondInstanceData.Args + + println("user opened second instance", strings.Join(secondInstanceData.Args, ",")) + println("user opened second from", secondInstanceData.WorkingDirectory) + runtime.WindowUnminimise(*wailsContext) + runtime.Show(*wailsContext) + go runtime.EventsEmit(*wailsContext, "launchArgs", secondInstanceArgs) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + OnStartup: app.startup, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx new file mode 100644 index 00000000000..4651c422ed1 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx @@ -0,0 +1,153 @@ +# SvelteKit + +This guide will go into: + +1. Miminal Installation Steps - The steps needed to get a minimum Wails setup working for SvelteKit. +2. Install Script - Bash script for accomplishing the Minimal Installation Steps with optional Wails branding. +3. Important Notes - Issues that can be encountered when using SvelteKit + Wails and fixes. + +## 1. Minimal Installation Steps + +##### Install Wails for Svelte. + +- `wails init -n myapp -t svelte` + +##### Delete the svelte frontend. + +- Navigate into your newly created myapp folder. +- Delete the folder named "frontend" + +##### While in the Wails project root. Use your favorite package manager and install SvelteKit as the new frontend. Follow the prompts. + +- `npm create svelte@latest frontend` + +##### Modify wails.json. + +- Add `"wailsjsdir": "./frontend/src/lib",` Do note that this is where your Go and runtime functions will appear. +- Change your package manager frontend here if not using npm. + +##### Modify main.go. + +- The first comment `//go:embed all:frontend/dist` needs to be changed to `//go:embed all:frontend/build` + +##### Install/remove dependencies using your favorite package manager. + +- Navigate into your "frontend" folder. +- `npm i` +- `npm uninstall @sveltejs/adapter-auto` +- `npm i -D @sveltejs/adapter-static` + +##### Change adapter in svelte.config.js + +- First line of file change `import adapter from '@sveltejs/adapter-auto';` to `import adapter from '@sveltejs/adapter-static';` + +##### Put SvelteKit into SPA mode with prerendering. + +- Create a file under myapp/frontend/src/routes/ named +layout.ts/+layout.js. +- Add two lines into the newly created file `export const prerender = true` and `export const ssr = false` + +##### Test installation. + +- Navigate back into the Wails project root (one directory up). +- run `wails dev` +- If the application doesn't run please check through the previous steps. + +## 2. Install Script + +##### This Bash Script does the steps listed above. Make sure to read over the script and understand what the script is doing on your computer. + +- Create a file sveltekit-wails.sh +- Copy the below code into the new file then save it. +- Make it executable with `chmod +x sveltekit-wails.sh` +- Brand is an optional param below that adds back in the wails branding. Leave third param blank to not insert the Wails branding. +- Example usage: `./sveltekit-wails.sh pnpm newapp brand` + +##### sveltekit-wails.sh: + +``` +manager=$1 +project=$2 +brand=$3 +wails init -n $project -t svelte +cd $project +sed -i "s|npm|$manager|g" wails.json +sed -i 's|"auto",|"auto",\n "wailsjsdir": "./frontend/src/lib",|' wails.json +sed -i "s|all:frontend/dist|all:frontend/build|" main.go +if [[ -n $brand ]]; then + mv frontend/src/App.svelte +page.svelte + sed -i "s|'./assets|'\$lib/assets|" +page.svelte + sed -i "s|'../wails|'\$lib/wails|" +page.svelte + mv frontend/src/assets . +fi +rm -r frontend +$manager create svelte@latest frontend +if [[ -n $brand ]]; then + mv +page.svelte frontend/src/routes/+page.svelte + mkdir frontend/src/lib + mv assets frontend/src/lib/ +fi +cd frontend +$manager i +$manager uninstall @sveltejs/adapter-auto +$manager i -D @sveltejs/adapter-static +echo -e "export const prerender = true\nexport const ssr = false" > src/routes/+layout.ts +sed -i "s|-auto';|-static';|" svelte.config.js +cd .. +wails dev +``` + +## 3. Important Notes + +##### Server files will cause build failures. + +- \+layout.server.ts, +page.server.ts, +server.ts or any file with "server" in the name will fail to build as all routes are prerendered. + +##### The Wails runtime unloads with full page navigations! + +- Anything that causes full page navigations: `window.location.href = '//'` or Context menu reload when using wails dev. What this means is that you can end up losing the ability to call any runtime breaking the app. There are two ways to work around this. +- Use `import { goto } from '$app/navigation'` then call `goto('//')` in your +page.svelte. This will prevent a full page navigation. +- If full page navigation can't be prevented the Wails runtime can be added to all pages by adding the below into the `` of myapp/frontend/src/app.html + +``` + +... + + + +... + +``` + +See https://wails.io/docs/guides/frontend for more information. + +##### Inital data can be loaded and refreshed from +page.ts/+page.js to +page.svelte. + +- \+page.ts/+page.js works well with load() https://kit.svelte.dev/docs/load#page-data +- invalidateAll() in +page.svelte will call load() from +page.ts/+page.js https://kit.svelte.dev/docs/load#rerunning-load-functions-manual-invalidation. + +##### Error Handling + +- Expected errors using Throw error works in +page.ts/+page.js with a +error.svelte page. https://kit.svelte.dev/docs/errors#expected-errors +- Unexpected errors will cause the application to become unusable. Only recovery option (known so far) from unexpected errors is to reload the app. To do this create a file myapp/frontend/src/hooks.client.ts then add the below code to the file. + +``` +import { WindowReloadApp } from '$lib/wailsjs/runtime/runtime' +export async function handleError() { + WindowReloadApp() +} +``` + +##### Using Forms and handling functions + +- The simplest way is to call a function from the form is the standard, bind:value your variables and prevent submission `
` +- The more advanced way is to use:enhance (progressive enhancement) which will allow for convenient access to formData, formElement, submitter. The important note is to always cancel() the form which prevents server side behavior. https://kit.svelte.dev/docs/form-actions#progressive-enhancement Example: + +``` + { + cancel() + console.log(Object.fromEntries(formData)) + console.log(formElement) + console.log(submitter) + handle() +}}> +``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx new file mode 100644 index 00000000000..790e3107f04 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx @@ -0,0 +1,97 @@ +# Templates + +Wails generates projects from pre-created templates. In v1, this was a difficult to maintain set of projects that were subject to going out of date. In v2, to empower the community, a couple of new features have been added for templates: + +- Ability to generate projects from [Remote Templates](../reference/cli.mdx#remote-templates) +- Tooling to help create your own templates + +## Creating Templates + +To create a template, you can use the `wails generate template` command. To generate a default template, run: + +`wails generate template -name mytemplate` + +This creates the directory "mytemplate" with default files: + +```shell title=mytemplate/ +. +|-- NEXTSTEPS.md +|-- README.md +|-- app.tmpl.go +|-- frontend +| `-- dist +| |-- assets +| | |-- fonts +| | | |-- OFL.txt +| | | `-- nunito-v16-latin-regular.woff2 +| | `-- images +| | `-- logo-dark.svg +| |-- index.html +| |-- main.css +| `-- main.js +|-- go.mod.tmpl +|-- main.tmpl.go +|-- template.json +`-- wails.tmpl.json +``` + +### Template Overview + +The default template consists of the following files and directories: + +| Filename / Dir | Description | +| --------------- | -------------------------------------------- | +| NEXTSTEPS.md | Instructions on how to complete the template | +| README.md | The README published with the template | +| app.tmpl.go | `app.go` template file | +| frontend/ | The directory containing frontend assets | +| go.mod.tmpl | `go.mod` template file | +| main.tmpl.go | `main.go` template file | +| template.json | The template metadata | +| wails.tmpl.json | `wails.json` template file | + +At this point it is advisable to follow the steps in `NEXTSTEPS.md`. + +## Creating a Template from an Existing Project + +It's possible to create a template from an existing frontend project by passing the path to the project when generating the template. We will now walk through how to create a Vue 3 template: + +- Install the vue cli: `npm install -g @vue/cli` +- Create the default project: `vue create vue3-base` + - Select `Default (Vue 3) ([Vue 3] babel, eslint)` +- After the project has been generated, run: + +```shell +> wails generate template -name wails-vue3-template -frontend .\vue3-base\ +Extracting base template files... +Migrating existing project files to frontend directory... +Updating package.json data... +Renaming package.json -> package.tmpl.json... +Updating package-lock.json data... +Renaming package-lock.json -> package-lock.tmpl.json... +``` + +- The template may now be customised as specified in the `NEXTSTEPS.md` file +- Once the files are ready, it can be tested by running: `wails init -n my-vue3-project -t .\wails-vue3-template\` +- To test the new project, run: `cd my-vue3-project` then `wails build` +- Once the project has compiled, run it: `.\build\bin\my-vue3-project.exe` +- You should have a fully functioning Vue3 application: + +```mdx-code-block +
+ +
+``` + +## Publishing Templates + +Publishing a template is simply pushing the files to GitHub. The following best practice is encouraged: + +- Remove any unwanted files and directories (such as `.git`) from your frontend directory +- Ensure that `template.json` is complete, especially `helpurl` +- Push the files to GitHub +- Create a PR on the [Community Templates](../community/templates.mdx) page +- Announce the template on the [Template Announcement](https://github.com/wailsapp/wails/discussions/825) discussion board diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx new file mode 100644 index 00000000000..1c3b6a9cc52 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx @@ -0,0 +1,368 @@ +# Troubleshooting + +An assortment of troubleshooting tips. + +## The `wails` command appears to be missing? + +If your system is reporting that the `wails` command is missing, make sure you have followed the Go installation guide correctly. Normally, it means that the `go/bin` directory in your User's home directory is not in the `PATH` environment variable. You will also normally need to close and reopen any open command prompts so that changes to the environment made by the installer are reflected at the command prompt. + +## My application is displaying a white/blank screen + +Check that your application includes the assets from the correct directory. In your `main.go` file, you will have something similar to the following code: + +```go +//go:embed all:frontend/dist +var assets embed.FS +``` + +Check that `frontend/dist` contains your application assets. + +### Mac + +If this happens on Mac, try adding the following to your `Info.plist`: + +```xml +NSAppTransportSecurity + + NSAllowsLocalNetworking + + +``` + +Reference: https://github.com/wailsapp/wails/issues/1504#issuecomment-1174317433 + +## Mac application not valid + +If your built application looks like this in finder: + +```mdx-code-block +

+ +

+``` + +it's likely that your application's `info.plist` is invalid. Update the file in `build/.app/Contents/info.plist` and check if the data is valid, EG check the binary name is correct. To persist the changes, copy the file back to the `build/darwin` directory. + +## My application is not displaying the correct icon in Windows Explorer + +If your application is not displaying the correct icon, try deleting the hidden `IconCache.db` file located in the `C:\Users\<your username>\AppData\Local` directory. This will force Windows to rebuild the icon cache. + +Source: https://github.com/wailsapp/wails/issues/2360#issuecomment-1556070036 + +## Cannot call backend method from frontend with variadic arguments + +If you have a backend method defined with variadic parameters, eg: + +```go +func (a *App) TestFunc(msg string, args ...interface{}) error { + // Code +} +``` + +calling this method from the frontend like this will fail: + +```js +var msg = "Hello: "; +var args = ["Go", "JS"]; +window.go.main.App.TestFunc(msg, ...args) + .then((result) => { + //do things here + }) + .catch((error) => { + //handle error + }); +``` + +Workaround: + +```js +var msg = "Hello "; +var args = ["Go", "JS"]; +window.go.main.App.TestFunc(msg, args) + .then((result) => { + //without the 3 dots + //do things here + }) + .catch((error) => { + //handle error + }); +``` + +Credit: https://github.com/wailsapp/wails/issues/1186 + +## I'm having getting proxy errors when trying to install Wails + +If you are getting errors like this: + +``` +"https://proxy.golang.org/github.com/wailsapp/wails/cmd/wails/@v/list": dial tcp 172.217.163.49:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. +``` + +it's probably because the official Go Proxy is being blocked (Users in China have reported this). The solution is to set up the proxy manually, eg: + +``` +go env -w GO111MODULE=on +go env -w GOPROXY=https://goproxy.cn,direct +``` + +Source: https://github.com/wailsapp/wails/issues/1233 + +## The generated TypeScript doesn't have the correct types + +Sometimes the generated TypeScript doesn't have the correct types. To mitigate this, it is possible to specify what types should be generated using the `ts_type` struct tag. For more details, please read [this](https://github.com/tkrajina/typescriptify-golang-structs#custom-types). + +## When I navigate away from `index.html`, I am unable to call methods on the frontend + +If you navigate away from `index.html` to a new html file, the context will be lost. This can be fixed by adding the following imports to the `` section of any new page you navigate to: + +```html + + + + +``` + +Source: https://github.com/wailsapp/wails/discussions/1512 + +## I get `too many open files` errors on my Mac when I run `wails dev` + +By default, macOS will only allow you to open a maximum of 256 files. This can affect the `wails dev` command. This limit can be increased by running: `ulimit -n 1024` in the terminal. + +FSNotify is [looking to move to Apple's fsevents](https://github.com/fsnotify/fsnotify/issues/11) for Mac. If this isn't completed soon, we will create our own implementation, tracked [here](https://github.com/wailsapp/wails/issues/1733). + +## My Mac app gives me weird compilation errors + +A few users have reported seeing compilation errors such as the following: + +```shell +# github.com/wailsapp/wails/v2/internal/frontend/desktop/darwin +In file included from ../../pkg/mod/github.com/wailsapp/wails/v2@v2.0.0-beta.44.2/internal/frontend/desktop/darwin/callbacks.go:9: +In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:12: +/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSBundle.h:91:143: error: function does not return NSString +- (NSAttributedString *)localizedAttributedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName NS_FORMAT_ARGUMENT(1) NS_REFINED_FOR_SWIFT API_AVAILABLE(macos(12.0), ios(15.0), watchos(8.0), tvos(15.0)); + ~~~~~~~~~~~~~~ ^ ~ +/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:103:48: note: expanded from macro 'NS_FORMAT_ARGUMENT' + #define NS_FORMAT_ARGUMENT(A) __attribute__ ((format_arg(A))) +``` + +This is _normally_ due to a mismatch with the OS version you are running and the version of the XCode Command Line Tools installed. If you see an error like this, try upgrading your XCode Command Line Tools to the latest version. + +If reinstalling Xcode Command Tools still fails, you can check the path where the toolkit is located using: + +`xcode-select -p` + +If `/Applications/Xcode.app/Contents/Developer` is displayed, run `sudo xcode-select --switch /Library/Developer/CommandLineTools` + +Sources: https://github.com/wailsapp/wails/issues/1806 and https://github.com/wailsapp/wails/issues/1140#issuecomment-1290446496 + +## My application won't compile on Mac + +If you are getting errors like this: + +```shell +l1@m2 GoEasyDesigner % go build -tags dev -gcflags "all=-N -l" +/Users/l1/sdk/go1.20.5/pkg/tool/darwin_arm64/link: running clang failed: exit status 1 +Undefined symbols for architecture arm64: + "_OBJC_CLASS_$_UTType", referenced from: + objc-class-ref in 000016.o +ld: symbol(s) not found for architecture arm64 +clang: error: linker command failed with exit code 1 (use -v to see invocation) +``` +Ensure you have the latest SDK installed. If so and you're still experiencing this issue, try the following: + +```shell +export CGO_LDFLAGS="-framework UniformTypeIdentifiers" && go build -tags dev -gcflags "all=-N -l" +``` + +Sources: https://github.com/wailsapp/wails/pull/2925#issuecomment-1726828562 + + +-- + +## Cannot start service: Host version "x.x.x does not match binary version "x.x.x" + +It's preferable to add `frontend/node_modules` and `frontend/package-lock.json` to your `.gitignore`. Otherwise when opening your repository on another machine that may have different versions of Node installed, you may not be able to run your application. + +If this does happen, simply delete `frontend/node_modules` and `frontend/package-lock.json` and run your `wails build` or `wails dev` command again. + +## Build process stuck on "Generating bindings" + +Bindings generation process runs your application in a special mode. If application, intentionally or unintentionally, contains an endless loop (i.e. not exiting after `wails.Run()` finished), this can lead to build process stuck on the stage of bindings generation. Please make sure your code exits properly. + +## Mac application flashes white at startup + +This is due to the default background of the webview being white. If you want to use the window background colour instead, you can make the webview background transparent using the following config: + +```go + err := wails.Run(&options.App{ + Title: "macflash", + Width: 1024, + Height: 768, + // Other settings + Mac: &mac.Options{ + WebviewIsTransparent: true, + }, + }) +``` + +## I get a "Microsoft Edge can't read or write to its data directory" error when running my program as admin on Windows + +You set your program to require admin permissions and it worked great! Unfortunately, some users are seeing a "Microsoft Edge can't read or write to its data directory" error when running it. + +When a Windows machine has two local accounts: + +- Alice, an admin +- Bob, a regular user + +Bob sees a UAC prompt when running your program. Bob enters Alice's admin credentials into this prompt. The app launches with admin permissions under Alice's account. + +Wails instructs WebView2 to store user data at the specified `WebviewUserDataPath`. It defaults to `%APPDATA%\[BinaryName.exe]`. + +Because the application is running under Alice's account, `%APPDATA%\[BinaryName.exe]` resolves to `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`. + +WebView2 [creates some child processes under Bob's logged-in account instead of Alice's admin account](https://github.com/MicrosoftEdge/WebView2Feedback/issues/932#issue-807464179). Since Bob cannot access `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`, the "Microsoft Edge can't read or write to its data directory" error is shown. + +Possible solution #1: + +Refactor your application to work without constant admin permissions. If you just need to perform a small set of admin tasks (such as running an updater), you can run your application with the minimum permissions and then use the `runas` command to run these tasks with admin permissions as needed: + +```go +//go:build windows + +package sample + +import ( + "golang.org/x/sys/windows" + "syscall" +) + +// Calling RunAs("C:\path\to\my\updater.exe") shows Bob a UAC prompt. Bob enters Alice's admin credentials. The updater launches with admin permissions under Alice's account. +func RunAs(path string) error { + verbPtr, _ := syscall.UTF16PtrFromString("runas") + exePtr, _ := syscall.UTF16PtrFromString(path) + cwdPtr, _ := syscall.UTF16PtrFromString("") + argPtr, _ := syscall.UTF16PtrFromString("") + + var showCmd int32 = 1 //SW_NORMAL + + err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd) + if err != nil { + return err + } + return nil +} +``` + +Possible solution #2: + +Run your application with extended permissions. If you absolutely must run with constant admin permissions, WebView2 will function correctly if you use a data directory accessible by both users and you also launch your app with the `SeBackupPrivilege`, `SeDebugPrivilege`, and `SeRestorePrivilege` permissions. Here's an example: + +```go +package main + +import ( + "embed" + "os" + "runtime" + + "github.com/fourcorelabs/wintoken" + "github.com/hectane/go-acl" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +//go:embed all:frontend/dist +var assets embed.FS + +const ( + fixedTokenKey = "SAMPLE_RANDOM_KEY" + fixedTokenVal = "with-fixed-token" + webviewDir = "C:\\ProgramData\\Sample" +) + +func runWithFixedToken() { + println("Re-launching self") + token, err := wintoken.OpenProcessToken(0, wintoken.TokenPrimary) //pass 0 for own process + if err != nil { + panic(err) + } + defer token.Close() + + token.EnableTokenPrivileges([]string{ + "SeBackupPrivilege", + "SeDebugPrivilege", + "SeRestorePrivilege", + }) + + cmd := exec.Command(os.Args[0]) + cmd.Args = os.Args + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", fixedTokenKey, fixedTokenVal)) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.SysProcAttr = &syscall.SysProcAttr{Token: syscall.Token(token.Token())} + if err := cmd.Run(); err != nil { + println("Error after launching self:", err) + os.Exit(1) + } + println("Clean self launch :)") + os.Exit(0) +} + +func main() { + if runtime.GOOS == "windows" && os.Getenv(fixedTokenKey) != fixedTokenVal { + runWithFixedToken() + } + + println("Setting data dir to", webviewDir) + if err := os.MkdirAll(webviewDir, os.ModePerm); err != nil { + println("Failed creating dir:", err) + } + if err := acl.Chmod(webviewDir, 0777); err != nil { + println("Failed setting ACL on dir:", err) + } + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "sample-data-dir", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + Windows: &windows.Options{ + WebviewUserDataPath: webviewDir, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +If you use a data directory accessible by both users but not the extended privileges, you will receive a WebView2 `80010108 The object invoked has disconnected from its clients` error. + +Possible future solution #3: [run WebView2 using an in-memory mode if implemented](https://github.com/MicrosoftEdge/WebView2Feedback/issues/3637#issuecomment-1728300982). + +## WebView2 installation succeeded, but the wails doctor command shows that it is not installed + +If you have installed WebView2, but the `wails doctor` command shows that it is not installed, it is likely that the WebView2 runtime installed was for a different architecture. You can download the correct runtime from [here](https://developer.microsoft.com/en-us/microsoft-edge/webview2/). + +Source: https://github.com/wailsapp/wails/issues/2917 + +## WebVie2wProcess failed with kind + +If your Windows app generates this kind of error, you can check out what the error means [here](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2processfailedkind?view=webview2-winrt-1.0.2045.28). + diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx new file mode 100644 index 00000000000..ed258656d63 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx @@ -0,0 +1,82 @@ + +# Visual Studio Code + +This page is for miscellaneous tips and tricks when using Visual Studio Code with Wails. + +## Vetur Configuration + +Many thanks to [@Lyimmi](https://github.com/Lyimmi) for this tip. Originally posted [here](https://github.com/wailsapp/wails/issues/1791#issuecomment-1228158349). + +Vetur is a popular plugin for Visual Studio Code that provides syntax highlighting and code completion for Vue projects. When loading a Wails project in VSCode, Vetur will throw an error as it is expecting to find the frontend project in the root directory. To fix this, you can do the following: + +Create a file named `vetur.config.js` in the project's root. + +```javascript +// vetur.config.js +/** @type {import('vls').VeturConfig} */ +module.exports = { + // **optional** default: `{}` + // override vscode settings + // Notice: It only affects the settings used by Vetur. + settings: { + "vetur.useWorkspaceDependencies": true, + "vetur.experimental.templateInterpolationService": true + }, + // **optional** default: `[{ root: './' }]` + // support monorepos + projects: [ + { + // **required** + // Where is your project? + // It is relative to `vetur.config.js`. + // root: './packages/repo1', + root: './frontend', + // **optional** default: `'package.json'` + // Where is `package.json` in the project? + // We use it to determine the version of vue. + // It is relative to root property. + package: './package.json', + // **optional** + // Where is TypeScript config file in the project? + // It is relative to root property. + tsconfig: './tsconfig.json', + // **optional** default: `'./.vscode/vetur/snippets'` + // Where is vetur custom snippets folders? + snippetFolder: './.vscode/vetur/snippets', + // **optional** default: `[]` + // Register globally Vue component glob. + // If you set it, you can get completion by that components. + // It is relative to root property. + // Notice: It won't actually do it. You need to use `require.context` or `Vue.component` + globalComponents: [ + './src/components/**/*.vue' + ] + } + ] +} +``` + +Next, configure `frontend/tsconfig.json`: + +```javascript +{ + "compilerOptions": { + "module": "system", + "noImplicitAny": true, + "removeComments": true, + "preserveConstEnums": true, + "sourceMap": true, + "outFile": "../../built/local/tsc.js", + "allowJs": true + }, + "exclude": [ + "node_modules", + "**/*.spec.ts" + ], + "include": [ + "src/**/*", + "wailsjs/**/*.ts" + ] +} +``` +This should enable you to now use Vetur as expected. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx new file mode 100644 index 00000000000..a819d070d3e --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx @@ -0,0 +1,58 @@ +# Installateur NSIS + +```mdx-code-block +

+ +
+

+``` + +Wails prend en charge la génération d'installateurs Windows en utilisant l'installateur [NSIS](https://nsis.sourceforge.io/). + +## Installation de NSIS + +### Windows + +L'installateur est disponible sur la page [de téléchargement NSIS](https://nsis.sourceforge.io/Download). + +Si vous utilisez le gestionnaire de paquets chocolatey, exécutez le script suivant : + +``` +choco install nsis +``` + +Si vous installez NSIS manuellement, vous devez ajouter le dossier _Bin_ , qui contient `makensis.exe`, dans la variable d'environnement PATH. [Cette page](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/) est un bon tutoriel sur comment ajouter un dossier dans votre variable d'environnement PATH sur Windows. + +### Linux + +Le paquet `nsis` devrait être disponible via le gestionnaire de paquets de votre distribution. + +### MacOS + +NSIS est disponible via homebrew en utilisant : `brew install nsis`. + +## Génération de l'installateur + +Lorsqu'un nouveau projet est créé, Wails génère les fichiers de configuration NSIS dans `build/windows/installer`. La configuration est lue dans `installer/info.json`, et est configuré pour utiliser la section info du fichier `wails.json` : + +```json +// ... + "Info": { + "companyName": "My Company Name", + "productName": "Wails Vite", + "productVersion": "1.0.0", + "copyright": "Copyright.........", + "comments": "Built using Wails (https://wails.io)" + }, +``` + +Pour générer l'installateur de votre application, utilisez l'option `-nsis` avec la commande `wails build`: + +``` +wails build -nsis +``` + +L'installateur sera ensuite disponible dans le dossier `build/bin`. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx new file mode 100644 index 00000000000..6b24979d741 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx @@ -0,0 +1,61 @@ +# Windows + +This page has miscellaneous guides related to developing Wails applications for Windows. + +## Handling the WebView2 Runtime Dependency + +Wails applications built for Windows have a runtime requirement on the Microsoft [WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/). Windows 11 will have this installed by default, but some machines won't. Wails offers an easy approach to dealing with this dependency. + +By using the `-webview2` flag when building, you can decide what your application will do when a suitable runtime is not detected (including if the installed runtime is too old). The four options are: + +1. Download +2. Embed +3. Navigateur +4. Error + +### Download + +This option will prompt the user that no suitable runtime has been found and then offer to download and run the official bootstrapper from Microsoft's WebView2 site. If the user proceeds, the official bootstrapper will be downloaded and run. + +### Embed + +This option embeds the official bootstrapper within the application. If no suitable runtime has been found, the application will offer to run the bootstrapper. This adds ~150k to the binary size. + +### Navigateur + +This option will prompt the user that no suitable runtime has been found and then offer to open a browser to the official WebView2 page where the bootstrapper can be downloaded and installed. The application will then exit, leaving the installation up to the user. + +### Error + +If no suitable runtime is found, an error is given to the user and no further action taken. + +## Fixed version runtime + +Another way of dealing with webview2 dependency is shipping it yourself. You can download [fixed version runtime](https://developer.microsoft.com/microsoft-edge/webview2/#download-section) and bundle or download it with your application. + +Also, you should specify path to fixed version of webview2 runtime in the `windows.Options` structure when launching wails. + +```go + wails.Run(&options.App{ + Windows: &windows.Options{ + WebviewBrowserPath: "", + }, + }) +``` + +Note: When `WebviewBrowserPath` is specified, `error` strategy will be forced in case of minimal required version mismatch or invalid path to a runtime. + +## Spawning other programs + +When spawning other programs, such as scripts, you will see the window appear on the screen. To hide the window, you can use the following code: + +```go +cmd := exec.Command("your_script.exe") +cmd.SysProcAttr = &syscall.SysProcAttr{ + HideWindow: true, + CreationFlags: 0x08000000, +} +cmd.Start() +``` + +Solution provided by [sithembiso](https://github.com/sithembiso) on the [discussions board](https://github.com/wailsapp/wails/discussions/1734#discussioncomment-3386172). diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx new file mode 100644 index 00000000000..0a6544735ee --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx @@ -0,0 +1,369 @@ +--- +sidebar_position: 20 +--- + +# Comment ça marche ? + +Une application Wails est une application Go standard, avec une interface graphique webkit. La partie Go de l'application se compose du code de l'application et d'une bibliothèque d'exécution qui fournit un certain nombre d'opérations utiles, comme le contrôle de la fenêtre de l'application. Le frontend est une fenêtre webkit qui affichera les ressources graphiques. Une version de la bibliothèque runtime de Javascript est aussi disponible depuis le frontend. Enfin, il est possible de lier les méthodes Go au frontend, et ceux-ci apparaîtront comme des méthodes Javascript qui peuvent être appelées, comme s'il s'agissait de méthodes locales Javascript. + +```mdx-code-block +
+ +
+``` + +## L'Application Principale + +### Vue d’ensemble + +L'application principale consiste en un seul appel à `wails.Run()`. Il accepte la configuration de l'application qui décrit la taille de la fenêtre d'application, le titre de la fenêtre, qu'elles sont les ressources à utiliser, etc. Une application de base pourrait ressembler à ceci : + +```go title="main.go" +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + + app := &App{} + + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + + +type App struct { + ctx context.Context +} + +func (b *App) startup(ctx context.Context) { + b.ctx = ctx +} + +func (b *App) shutdown(ctx context.Context) {} + +func (b *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +### Description des options + +Cet exemple a les options suivantes : + +- `Title` - Le texte qui devrait apparaître dans la barre de titre de la fenêtre +- `Width` & `Height` - Les dimensions de la fenêtre +- `Assets` - Les ressources du frontend de l'application +- `OnStartup` - Nom de la fonction à appeler quand la fenêtre est créée et est sur le point de commencer à charger les ressources du frontend +- `OnShutdown` - Nom de la fonction à appeler quand la fenêtre est sur le point d'être fermée +- `Bind` - La liste des structures Go à exposer au frontend + +Une liste complète des options d'application peut être trouvée dans la [Référence d'options](reference/options). + +#### Ressources + +L'option `Assets` est obligatoire car vous ne pouvez pas avoir d'application Wails sans ressources en frontend. Ces ressources peuvent être n'importe quel fichier que vous attendriez à trouver dans une application web - html, js, css, svg, png, etc. **Il n'y a aucune obligation d'utiliser un générateur de code ou framework** - des fichiers bruts suffisent. Lorsque l'application démarre, elle tentera de charger le fichier `index.html` à partir de vos ressources et le frontend fonctionnera essentiellement comme un navigateur à partir de ce point. Il est intéressant de noter que il n'y a pas de condition sur l'emplacement de `embed.FS`. Il est probable que le chemin d'intégration utilise un répertoire imbriqué par rapport au code de votre application principale, comme `frontend/dist`: + +```go title="main.go" +//go:embed all:frontend/dist +var assets embed.FS +``` + +Au démarrage, Wails va itérer les fichiers embarqués à la recherche du répertoire contenant `index.html`. Tous les autres actifs seront chargés par rapport à à ce répertoire. + +Comme les binaires de production utilisent les fichiers contenus dans `embed.FS`, il n'y a aucun fichier externe requis pour être expédié avec l'application. + +Lorsque vous exécutez en mode développement en utilisant la commande `wails dev` , les assets sont chargés à partir du disque, et tous les changements résultent en un "rechargement en direct". L'emplacement des actifs sera déduit de la `embed.FS`. + +Plus de détails peuvent être trouvés dans le [Guide de développement d'applications](guides/application-development.mdx). + +#### Callbacks du cycle de vie de l'application + +Juste avant que le frontend ne soit sur le point de charger `index.html`, un callback est fait à la fonction fournie dans [OnStartup](reference/options.mdx#onstartup). Un contexte standard Go est passé à cette méthode. Ce contexte est requis lors de l'appel à l'exécution, donc une bonne pratique est de sauvegarder une référence dans cette méthode. Juste avant que l'application ne s'arrête, la fonction de rappel [OnShutdown](reference/options.mdx#onshutdown) est appelée de la même manière, à nouveau avec le contexte. Il y a aussi un callback [OnDomReady](reference/options.mdx#ondomready) pour quand le frontend a terminé le chargement de tous les assets de `index.html` et est équivalent à l'événement [`body onload`](https://www.w3schools.com/jsref/event_onload.asp) en JavaScript. Il est également possible de s'accrocher à l'événement de fermeture de la fenêtre (ou de quitter l'application) en définissant l'option [OnBeforeClose](reference/options.mdx#onbeforeclose). + +#### Binding de méthodes + +L'option `Bind` est l'une des options les plus importantes dans une application Wails. Il spécifie quelles méthodes de structs sont à exposer au frontend. Pensez à des "contrôleurs" dans une application web traditionnelle. Quand l'application démarre, elle examine les instances structurées listées dans l'option `Bind`, détermine quelles méthodes sont publiques (commence par une lettre majuscule) et générera des versions JavaScript de ces méthodes qui peuvent être appelées par le code en frontend. + +:::info Note + +Wails exige que vous passiez dans une _instance_ du struct pour qu'il le lie correctement + +::: + +Dans cet exemple, nous créons une nouvelle instance `App` puis ajoutons cette instance à l'option `Bind` dans `wails.Run`: + +```go {17,27} title="main.go" +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + + app := &App{} + + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + + +type App struct { + ctx context.Context +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +Vous pouvez lier autant de structures que vous le souhaitez. Assurez-vous juste de créer une instance de celle-ci et de la passer dans `Bind`: + +```go {10-12} + //... + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + &mystruct1{}, + &mystruct2{}, + }, + }) + +``` + +Lorsque vous exécutez `wails dev` (ou `wails generate module`), un module frontend sera généré contenant les éléments suivants : + +- JavaScript bindings pour toutes les méthodes liées +- Déclarations TypeScript pour toutes les méthodes liées +- Définitions TypeScript pour toutes les structures Go utilisées comme entrées ou sorties par les méthodes liées + +Cela rend incroyablement simple d'appeler le code Go depuis le frontend, en utilisant les mêmes structures de données. + +## Le frontend + +### Vue d’ensemble + +Le frontend est une collection de fichiers rendus par webkit. C'est comme un navigateur et un serveur web en un. Il y a virtuellement[^1] aucune limite vis à vis des frameworks ou des bibliothèques que vous pouvez utiliser. Les principaux points d'interaction entre le frontend et votre code Go sont: + +- L'appel des méthodes Go liées +- L'appel des méthodes d'exécution + +### L'appel des méthodes Go liées + +Lorsque vous exécutez votre application avec `wails dev`, il générera automatiquement des liaisons JavaScript pour vos structures dans un répertoire appelé `wailsjs/go` (Vous pouvez aussi le faire en exécutant `wails generate module`). Les fichiers générés reflètent les noms de paquets dans votre application. Dans l'exemple ci-dessus, nous associons `app`, qui a une méthode publique `Greet`. Cela conduira à la génération des fichiers suivants : + +```bash +wailsjs + └─go + └─main + ├─App.d.ts + └─App.js +``` + +Ici nous pouvons voir qu'il y a un dossier `main` qui contient les liaisons JavaScript pour la structure `App` liée, ainsi que que le fichier de déclaration TypeScript pour ces méthodes. Pour appeler `Greet` depuis notre frontend, nous importons simplement la méthode et l'appelons comme une fonction JavaScript régulière: + +```javascript +// ... +import { Greet } from "../wailsjs/go/main/App"; + +function doGreeting(name) { + Greet(name).then((result) => { + // Do something with result + }); +} +``` + +La déclaration en TypeScript vous donne les bons types pour les méthodes paramètres et la valeur retournée : + +```ts +export function Greet(arg1: string): Promise; +``` + +Les méthodes générées retournent une Promise. Un appel réussi entraînera la première valeur de retour de l'appel Go à passer au `resolve` handler. Un appel infructueux est quand une méthode Go qui a un type d'erreur comme valeur de deuxième retour, passe une erreur à l'appelant. Ceci est passé en arrière via le handler `reject`. Dans l'exemple ci-dessus, `Greet` ne retourne qu'un `string` donc l'appel JavaScript ne sera jamais rejeté - à moins que des données non valides ne lui soient passées. + +Tous les types de données sont correctement traduits entre Go et JavaScript. Même les structs. Si vous renvoyez un struct d'un appel Go, il sera retourné à votre frontend en tant que classe JavaScript. + +:::info Note + +Les champs Struct _doivent avoir_ le champ `json` de défini afin de pouvoir l'inclure dans le TypeScript généré. + +Les structures imbriquées anonymes ne sont pas supportées pour le moment. + +::: + +Il est possible d'envoyer des structures à Go. N'importe quelle map/classe JavaScript passée comme argument, sera convertie en son équivalent. Pour faciliter ce processus, en mode `dev` un module TypeScript est généré, définissant tous les types de structures utilisés dans les méthodes liées. En utilisant ce module, il est possible de construire et envoyer des objets JavaScript natifs au code Go. + +Il y a aussi le support des méthodes Go qui utilisent les structures dans leur signature. Toutes les structures Go spécifiées par une méthode liée (que ce soit en tant que paramètres ou types de retour) auront les versions TypeScript automatiques générées dans le module de gestion de code Go. En utilisant ceux-ci, il est possible de partager le même modèle de données entre Go et JavaScript. + +Exemple: Nous mettons à jour notre méthode `Greet` pour accepter une `Person` au lieu d'une chaîne de caractères : + +```go title="main.go" +type Person struct { + Name string `json:"name"` + Age uint8 `json:"age"` + Address *Address `json:"address"` +} + +type Address struct { + Street string `json:"street"` + Postcode string `json:"postcode"` +} + +func (a *App) Greet(p Person) string { + return fmt.Sprintf("Hello %s (Age: %d)!", p.Name, p.Age) +} +``` + +Le fichier `wailsjs/go/main/App.js` aura toujours le code suivant : + +```js title="App.js" +export function Greet(arg1) { + return window["go"]["main"]["App"]["Greet"](arg1); +} +``` + +Mais le fichier `wailsjs/go/main/App.d.ts` sera mis à jour avec le code suivant : + +```ts title="App.d.ts" +import { main } from "../models"; + +export function Greet(arg1: main.Person): Promise; +``` + +Comme nous pouvons le voir, le namespace "main" est importé à partir du nouveau fichier "models.ts". Ce fichier contient toutes les définitions de struct utilisées par nos méthodes liées. Dans cet exemple, c'est une struct `Person`. Si nous regardons `models.ts`, nous pouvons voir comment les modèles sont définis : + +```ts title="models.ts" +export namespace main { + export class Address { + street: string; + postcode: string; + + static createFrom(source: any = {}) { + return new Address(source); + } + + constructor(source: any = {}) { + if ("string" === typeof source) source = JSON.parse(source); + this.street = source["street"]; + this.postcode = source["postcode"]; + } + } + export class Person { + name: string; + age: number; + address?: Address; + + static createFrom(source: any = {}) { + return new Person(source); + } + + constructor(source: any = {}) { + if ("string" === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.age = source["age"]; + this.address = this.convertValues(source["address"], Address); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice) { + return (a as any[]).map((elem) => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } +} +``` + +Tant que vous avez TypeScript dans votre configuration de compilation en frontend, vous pouvez utiliser ces modèles de la manière suivante: + +```js title="mycode.js" +import { Greet } from "../wailsjs/go/main/App"; +import { main } from "../wailsjs/go/models"; + +function generate() { + let person = new main.Person(); + person.name = "Peter"; + person.age = 27; + Greet(person).then((result) => { + console.log(result); + }); +} +``` + +La combinaison des liaisons générées et des modèles TypeScript crée un environnement de développement puissant. + +Plus d'informations sur la liaison peuvent être trouvées dans la section [Méthodes de liaison](guides/application-development.mdx#binding-methods) de la [Guide de développement d'applications](guides/application-development.mdx). + +### Appeler les méthodes runtime + +Le runtime JavaScript se trouve dans `window.runtime` et contient de nombreuses méthodes pour faire diverses tâches telles qu'émettre un événement ou effectuer des opérations de journalisation : + +```js title="mycode.js" +window.runtime.EventsEmit("my-event", 1); +``` + +Plus de détails sur l'exécutable JS peuvent être trouvés dans la [Référence d'exécution](reference/runtime/intro). + +[^1]: Il y a un très petit sous-ensemble de bibliothèques qui utilisent des fonctionnalités non prises en charge dans WebViews. Il y a souvent des alternatives et des solutions de contournement pour de tels cas. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx new file mode 100644 index 00000000000..680c0bba22a --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx @@ -0,0 +1,75 @@ +--- +sidebar_position: 1 +--- + +# Introduction + +Wails est un projet qui vous permet d'écrire des applications de bureau en utilisant les technologies Go et web. + +Considérez cela comme une alternative légère et rapide d'Electron pour Go. Vous pouvez facilement construire des applications avec la flexibilité et la puissance de Go, combinée à un frontend riche et moderne. + +### Fonctionnalités + +- Menus natifs, Boîtes de dialogues, Thèmes et Translucidité +- Prise en charge de Windows, macOS et Linux +- Modèles intégrés pour Svelte, React, Preact, Vue, Lit et Vanilla JS +- Appeler facilement les méthodes Go depuis JavaScript +- Génération automatique du modèle TypeScript à partir des struct Go +- Aucun CGO ou DLL externe requis sous Windows +- Mode développement en direct en utilisant la puissance de [Vite](https://vitejs.dev/) +- CLI puissant pour créer, construire et empaqueter facilement des applications +- Une riche bibliothèque [runtime](/docs/reference/runtime/intro) +- Les applications construites avec Wails sont conformes aux Stores Apple & Microsoft + +Ceci est [varly](https://varly.app) - une application de bureau pour MacOS & Windows écrite à l'aide de Wails. Non seulement elle est belle, elle utilise les menus natifs et la translucidité - tout ce que vous pouvez attendre d'une application native moderne. + +```mdx-code-block +

+ + + +

+``` + +### Modèles de créations rapides + +Wails est livré avec un certain nombre de modèles préconfigurés qui vous permettent de faire fonctionner votre application rapidement. Il y a des modèles pour les frameworks suivants : Svelte, React, Vue, Preact, Lit et Vanilla. Il existe à la fois des versions JavaScript et TypeScript pour chaque modèle. + +### Éléments natifs + +Wails utilise une bibliothèque conçue pour gérer les éléments natifs tels que les fenêtres, menus, boîtes de dialogues, etc, pour que vous puissiez construire des applications de bureau riches en fonctionnalités. + +**It does not embed a browser**, so it delivers a small runtime. Instead, it reuses the native rendering engine for the platform. Sous Windows, c'est la nouvelle bibliothèque Microsoft Webview2, construite sur Chromium. + +### Interopérabilité Go & Javascript + +Wails met automatiquement vos méthodes Go à la disposition de Javascript, afin que vous puissiez les appeler par nom depuis votre frontend ! Il génère même des modèles Typescript pour les structures utilisées par vos méthodes Go, pour que vous puissiez passer les mêmes structures de données entre Go et Javascript. + +### Librairie d'exécution + +Wails fournit une bibliothèque runtime, pour Go et Javascript, qui gère beaucoup de choses dont les applications modernes ont besoin, comme Logging, Boîtes de dialogue, etc. + +### Expérience de développement en direct + +#### Reconstructions automatiques + +Lorsque vous exécutez votre application en mode "dev", Wails construira votre application en tant qu'application de bureau native, mais lira vos ressources depuis le disque. Il détectera toutes les modifications apportées à votre code Go, puis reconstruira et relancera automatiquement votre application . + +#### Rechargement automatique + +Lorsque des changements sont détectés dans les ressources de votre application, votre application en cours d'exécution sera "rechargée", reflétant presque immédiatement vos modifications . + +#### Développez votre application dans un navigateur + +Si vous préférez déboguer et vous développer dans un navigateur, Wails vous couvre. L'application en cours d'exécution a également un serveur web qui exécutera votre application depuis n'importe quel navigateur qui s'y connecte. Il sera aussi actualisé lorsque vos fichiers seront modifiés. + +### Binaires natifs prêts à la production + +Lorsque vous êtes prêt à faire une version finale de votre application, le CLI le compilera en un seul exécutable, avec tous les actifs qui y sont intégrés. Sous Windows et MacOS, il est possible de créer un paquet natif pour la distribution. Les ressources utilisées dans la compilation de l'application (icône, info. list, fichier manifest, etc) font partie de votre projet et peuvent être personnalisés, ce qui vous donne le contrôle total sur la façon dont vos applications sont construites. + +### Outils + +Le CLI Wails fournit un moyen sans tracas de générer, de construire et de regrouper vos applications. Il s'occupera de la lourde tâche de créer des icônes, de compiler votre application avec des paramètres optimaux et de fournir un binaire distribuable et prêt à la production. Choisissez parmi un certain nombre de modèles de démarrage pour démarrer rapidement ! diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx new file mode 100644 index 00000000000..30721c11204 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx @@ -0,0 +1,241 @@ +--- +sidebar_position: 2 +--- + +# CLI + +Le CLI Wails a un certain nombre de commandes qui sont utilisées pour gérer vos projets. Toutes les commandes sont exécutées de la manière suivante: + +`wails ` + +## init + +`wails init` est utilisé pour générer des projets. + +| Option | Description | Par défaut | +|:------------------------- |:---------------------------------------------------------------------------------------------------------------------- |:-------------:| +| -n "nom du projet" | Nom du projet. **Obligatoire**. | | +| -d "Répertoire du projet" | Dossier de projet à créer | Nom du projet | +| -g | Initialisation du dépôt git | | +| -l | Liste des modèles de projet disponibles | | +| -q | Supprimer les logs dans la console | | +| -t "nom du modèle" | Modèle de projet à utiliser. Cela peut être le nom d'un modèle par défaut ou d'une URL d'un projet hébergé sur github. | vanilla | +| -ide | Générer les fichiers du projet IDE | | +| -f | Forcer la compilation de l'application | false | + +Exemple: `wails init -n test -d mytestproject -g -ide vscode -q` + +Cela va générer un projet appelé "test" dans le répertoire "mytestproject", initialiser git, générer des fichiers de projet vscode et le faire silencieusement. + +Plus d'informations sur l'utilisation des IDEs avec Wails peuvent être trouvées [ici](../guides/ides.mdx). + +### Modèles à distance + +Les modèles distants (hébergés sur GitHub) sont pris en charge et peuvent être installés en utilisant l'URL du projet du modèle. + +Exemple : `wails init -n test -t https://github.com/leaanthony/testtemplate[@v1.0.0]` + +Une liste de modèles gérés par la communauté peut être trouvée [ici](../community/templates.mdx) + +:::warning Attention + +**Le projet Wails n'entretient pas, n'est pas responsable ni responsable des modèles tiers !** + +Si vous n'êtes pas sûr d'un modèle, inspectez les fichiers `package.json` et `wails.json` pour savoir quels scripts sont exécutés et quels paquets sont installés. + +::: + +## build + +`wails build` est utilisé pour compiler votre projet vers un binaire prêt à la production. + +| Option | Description | Par défaut | +|:-------------------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| -clean | Nettoie le répertoire `build/bin` | | +| -compiler "compiler" | Utiliser un autre compilateur pour compiler, par exemple go1.15beta1 | go | +| -debug | Conserve les informations de débogage dans l'application et affiche la console de débogage. Permet l'utilisation des outils de développement dans la fenêtre de l'application | | +| -devtools | Allows the use of the devtools in the application window in production (when -debug is not used). Ctrl/Cmd+Shift+F12 may be used to open the devtools window. *NOTE*: This option will make your application FAIL Mac appstore guidelines. Use for debugging only. | | +| -dryrun | Affiche la commande build sans l'exécuter | | +| -f | Forcer la compilation de l'application | | +| -garbleargs | Arguments à passer à garble | `-literals -tiny -seed=random` | +| -ldflags "flags" | Options supplémentaires à passer au compilateur | | +| -m | Permet d'ignorer mod tidy avant la compilation | | +| -nopackage | Ne pas empaqueter l'application | | +| -nocolour | Désactive la couleur des logs dans le terminal | | +| -nosyncgomod | Ne pas synchroniser go.mod avec la version Wails | | +| -nsis | Génère l'installateur NSIS pour Windows | | +| -o filename | Nom du fichier de sortie | | +| -obfuscated | Cacher le code de l'application en utilisant [garble](https://github.com/burrowers/garble) | | +| -platform | Construit pour les [plates-formes](../reference/cli.mdx#platforms) données (séparées par des virgules) par exemple. `windows/arm64`. Notez que si vous ne donnez pas l'architecture, `runtime.GOARCH` est utilisé. | platform = le contenu de la variable d'environnement `GOOS` si elle existe, autrement `runtime.GOOS`.
arch = le contenu de la variable d'environnement `GOARCH` si elle existe, autrement `runtime.GOARCH`. | +| -race | Construire avec le détecteur Go race | | +| -s | Ignorer la construction du frontend | | +| -skipbindings | Ignorer la génération des liaisons | | +| -tags "extra tags" | Options de compilation à passer au compilateur Go. Doivent être entre guillemets. Séparés par un espace ou une virgule (pas les deux) | | +| -trimpath | Supprimer tous les chemins vers les fichiers système de l'exécutable final. | | +| -u | Met à jour le `go.mod de votre projet` pour utiliser la même version de Wails que le CLI | | +| -upx | Compresser le binaire final en utilisant "upx" | | +| -upxflags | Options à passer à upx | | +| -v int | Niveau de verbosité (0 - silencieux, 1 - par défaut, 2 - verbeux) | 1 | +| -webview2 | Stratégie d'installation WebView2 : download,embed,browser,error | download | +| -windowsconsole | Garder la fenêtre de la console lors de la construction d'une version pour Windows | | + +Pour une description détaillée des options `webview2` , veuillez vous référer au Guide de [Windows](../guides/windows.mdx). + +Si vous préférez construire en utilisant l'outil Go standard, veuillez consulter le guide [Constructions manuelles](../guides/manual-builds.mdx) . + +Exemple: + +`wails build -clean -o myproject.exe` + +:::info + +Info +Sur Mac, l'application sera livrée avec `Info.plist`, pas `Info.dev.plist`. + +::: + +:::info UPX sur Apple Silicon + +Il y a [problèmes](https://github.com/upx/upx/issues/446) avec l'utilisation de UPX avec Apple Silicon. + +::: + +:::info UPX sur Windows + +Certains antivirus marquent de manière erronée les binaires compressés d'`upx` comme virus, voir [la description du problème](https://github.com/upx/upx/issues/437). + +::: + +### Platformes + +Plateformes supportées: + +| Plateforme | Description | +|:---------------- |:-------------------------------------------------- | +| darwin | MacOS + Architecture de la machine de construction | +| darwin/amd64 | MacOS 10.13+ AMD64 | +| darwin/arm64 | MacOS 11.0+ ARM64 | +| darwin/universal | Application universelle MacOS AMD64+ARM64 | +| windows | Windows 10/11 + architecture de la machine | +| windows/amd64 | Windows 10/11 AMD64 | +| windows/arm64 | Windows 10/11 ARM64 | +| linux | Linux + architecture de la machine | +| linux/amd64 | Linux AMD64 | +| linux/arm64 | Linux ARM64 | + +## doctor + +`wails doctor` effectuera des diagnostics pour vous assurer que votre système est prêt pour développer avec wails. + +Exemple: + +``` +Wails CLI v2.0.0-beta + +Scanning system - Please wait (this may take a long time)...Done. + +System +------ +OS: Windows 10 Pro +Version: 2009 (Build: 19043) +ID: 21H1 +Go Version: go1.18 +Platform: windows +Architecture: amd64 + +Dependency Package Name Status Version +---------- ------------ ------ ------- +WebView2 N/A Installed 93.0.961.52 +npm N/A Installed 6.14.15 +*upx N/A Installed upx 3.96 + +* - Optional Dependency + +Diagnosis +--------- +Your system is ready for Wails development! + +``` + +## dev + +`wails dev` est utilisé pour exécuter votre application en mode « développement en direct ». Ceci signifie que : + +- Le fichier `go.mod` de l'application sera mis à jour pour utiliser la même version de Wails que le CLI +- L'application est compilée et exécutée automatiquement +- Un observateur est démarré et déclenchera une reconstruction de votre application de développement s'il détecte des changements dans vos fichiers go +- Un serveur web est lancé sur `http://localhost:34115` qui sert votre application (et pas seulement le frontend) sur http. Cela vous permet d'utiliser les extensions de développement de votre navigateur favori +- Tous les assets de l'application sont chargés à partir du disque. Si elles sont modifiées, l'application se rechargera automatiquement (pas de recompilation). Tous les navigateurs connectés rechargeront également +- Un module JS est généré fournissant les éléments suivants : +- Les méthodes Javascript permettant d'appeler vos méthodes Go avec JSDoc autogénérée, vous fournissant des indications sur les méthodes +- Les versions TypeScript de vos structures Go, qui peuvent être construites et transmises à vos méthodes +- Un second module JS est généré qui fournit une déclaration des méthodes et structures pour l'exécutable +- Sur macOS, il regroupera l'application dans un fichier `.app` et l'exécutera. Il utilisera un `build/darwin/Info.dev.plist` pour le développement. + +| Option | Description | Par défaut | +|:------------------------------------ |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |:------------------------ | +| -appargs "args" | Arguments passés à l'application en style shell | | +| -assetdir "./chemin/vers/les/assets" | Sert les assets depuis le répertoire donné au lieu d'utiliser le fichier FS fourni | Valeur dans `wails.json` | +| -browser | Ouvre un navigateur à `http://localhost:34115` au démarrage | | +| -compiler "compiler" | Utiliser un autre compilateur pour compiler, par exemple go1.15beta1 | go | +| -debounce | Le temps d'attente pour le rechargement après qu'une modification d'actif est détectée | 100 (millisecondes) | +| -devserver "host:port" | L'adresse à laquelle lier le serveur de développement wails | "localhost:34115" | +| -extensions | Extensions pour déclencher les rebuilds (séparés par des virgules) | go | +| -forcebuild | Force la compilation de l'application | | +| -frontenddevserverurl "url" | Utiliser l'url du serveur de développement tiers pour servir les actifs, EG Vite | "" | +| -ldflags "flags" | Options supplémentaires à passer au compilateur | | +| -loglevel "loglevel" | Niveau de log à utiliser - Trace, Debug, Info, Warning, Error | Debug | +| -nocolour | Désactiver la couleur dans le terminal | false | +| -noreload | Désactiver le rechargement automatique lorsque les actifs changent | | +| -nosyncgomod | Ne pas synchroniser go.mod avec la version Wails | false | +| -race | Construire avec le détecteur Go race | false | +| -reloaddirs | Répertoires supplémentaires pour déclencher les recharges (séparés par des virgules) | Valeur dans `wails.json` | +| -s | Ignorer la construction du frontend | false | +| -save | Sauvegarde les options `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce`, `devserver` and `frontenddevserverurl` dans `wails.json` pour quelles deviennent les informations par défaut pour les prochaines utilisations. | | +| -skipbindings | Ignorer la génération des liaisons | | +| -tags "extra tags" | Options de construction à passer au compilateur (séparées par des guillemets et des espaces) | | +| -v | Niveau de verbosité (0 - silencieux, 1 - par défaut, 2 - verbeux) | 1 | +| -wailsjsdir | Le répertoire où stocker les modules JS Wails générés | Valeur dans `wails.json` | + +Exemple: + +`wails dev -assetdir ./frontend/dist -wailsjsdir ./frontend/src -browser` + +Cette commande fera ce qui suit : + +- Construisez l'application et exécutez-la (plus de détails [ici](../guides/manual-builds.mdx) +- Générer les modules JS Wails dans `./frontend/src` +- Surveillez les mises à jour des fichiers dans `./frontend/dist` et rechargez en cas de changement +- Ouvre un navigateur et se connecte à l'application + +Il y a plus d'informations sur l'utilisation de cette fonctionnalité avec les scripts de framework existants [ici](../guides/application-development.mdx#live-reloading). + +## generate + +### template + +Wails utilise des modèles pour la génération de projets. La commande `wails génère le template` aide à échafauder un modèle afin que il puisse être utilisé pour générer des projets. + +| Option | Description | +|:---------------- |:-------------------------------------------------------- | +| -name | Le nom du modèle (Obligatoire) | +| -frontend "path" | Chemin vers le projet frontend à utiliser dans le modèle | + +Pour plus de détails sur la création de modèles, consultez le [Guide sur les modèles](../guides/templates.mdx). + +### module + +La commande `wails génère le module` vous permet de générer manuellement le répertoire `wailsjs` pour votre application. + +## update + +`wails update` va mettre à jour la version du CLI Wails. + +| Option | Description | +|:------------------ |:----------------------------------------------------- | +| -pre | Mettre à jour la version avec la dernière pre-release | +| -version "version" | Installer une version spécifique du CLI | + +## version + +`wails version` va simplement afficher la version actuelle du CLI. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx new file mode 100644 index 00000000000..80dbaa0c5cf --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx @@ -0,0 +1,230 @@ +--- +sidebar_position: 4 +--- + +# Menus + +Il est possible d'ajouter un menu applicatif aux projets Wails. Ceci est réalisé en définissant une structure [Menu](#menu) et en la définissant dans la configuration de l'application [`Menu`](../reference/options.mdx#menu) , ou en appelant la méthode d'exécution [MenuSetApplicationMenu](../reference/runtime/menu.mdx#menusetapplicationmenu). + +Un exemple de définition d'un menu : + +```go + + app := NewApp() + + AppMenu := menu.NewMenu() + FileMenu := AppMenu.AddSubmenu("File") + FileMenu.AddText("&Open", keys.CmdOrCtrl("o"), openFile) + FileMenu.AddSeparator() + FileMenu.AddText("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) { + runtime.Quit(app.ctx) + }) + + if runtime.GOOS == "darwin" { + AppMenu.Append(menu.EditMenu()) // on macos platform, we should append EditMenu to enable Cmd+C,Cmd+V,Cmd+Z... shortcut + } + + err := wails.Run(&options.App{ + Title: "Menus Demo", + Width: 800, + Height: 600, + Menu: AppMenu, // reference the menu above + Bind: []interface{}{ + app, + }, + ) + // ... +``` + +Il est également possible de mettre à jour dynamiquement le menu, en mettant à jour le menu struct et en appelant [MenuUpdateApplicationMenu](../reference/runtime/menu.mdx#menuupdateapplicationmenu). + +L'exemple ci-dessus utilise des méthodes d'aide, cependant il est possible de construire le menu manuellement. + +## Menu + +Un Menu est une collection de MenuItems: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +type Menu struct { + Items []*MenuItem +} +``` + +Pour le menu de l'application, chaque MenuItem représente un seul menu tel que "Edit". + +Une méthode simple d'aide est fournie pour les menus de construction : + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func NewMenuFromItems(first *MenuItem, rest ...*MenuItem) *Menu +``` + +Cela rend la mise en page du code plus semblable à celle d'un menu sans avoir à ajouter les éléments de menu manuellement après leur création. Vous pouvez également créer les liens de menu et les ajouter au menu manuellement. + +## MenuItem + +Un MenuItem représente un élément dans un Menu. + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +// MenuItem represents a menu item contained in a menu +type MenuItem struct { + Label string + Role Role + Accelerator *keys.Accelerator + Type Type + Disabled bool + Hidden bool + Checked bool + SubMenu *Menu + Click Callback +} +``` + +| Champ | Type | Notes | +| ----------- | ------------------------------------ | --------------------------------------------------------------------------------------- | +| Label | string | Le texte du menu | +| Accelerator | [\*keys.Accelerator](#accelerator) | Raccourci pour ce lien de menu | +| Type | [Type](#type) | Type de MenuItem | +| Disabled | bool | Désactive l'élément de menu | +| Hidden | bool | Masque cet élément de menu | +| Checked | bool | Ajoute une coche à l'élément (case à cocher & Types de radio) | +| SubMenu | [\*Menu](#menu) | Définit un sous-menu | +| Click | [Callback](#callback) | Fonction à appeler quand un click est fait sur cet élément du menu. | +| Role | string | Définit un rôle [](#role) pour cet élément de menu. Pour Mac seulement, pour le moment. | + +### Accelerator + +Les accélérateurs (parfois appelés raccourcis clavier) définissent une liaison entre une clé et un élément du menu. Wails définit un accélérateur comme une combinaison ou une clé + [modificateur](#modifier). Ils sont disponibles dans le paquet `"github.com/wailsapp/wails/v2/pkg/menu/keys"`. + +Exemple: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines cmd+o on Mac and ctrl-o on Window/Linux + myShortcut := keys.CmdOrCtrl("o") +``` + +Les clés sont n'importe quel caractère sur un clavier à l'exception de `+`, qui est défini comme `plus`. Certaines clés ne peuvent pas être représentées comme des caractères, il y a donc un ensemble de caractères nommés qui peuvent être utilisés : + +| | | | | +|:----------------:|:-----:|:-----:|:---------:| +| `retour arrière` | `f1` | `f16` | `f31` | +| `tabulation` | `f2` | `f17` | `f32` | +| `retour` | `f3` | `f18` | `f33` | +| `entrée` | `f4` | `f19` | `f34` | +| `echap` | `f5` | `f20` | `f35` | +| `gauche` | `f6` | `f21` | `numlock` | +| `droite` | `f7` | `f22` | | +| `haut` | `f8` | `f23` | | +| `bas` | `f9` | `f24` | | +| `espace` | `f10` | `f25` | | +| `suppr` | `f11` | `f36` | | +| `début` | `f12` | `f37` | | +| `fin` | `f13` | `f38` | | +| `page haut` | `f14` | `f39` | | +| `page bas` | `f15` | `f30` | | + +Wails prend également en charge l'analyse des accélérateurs en utilisant la même syntaxe qu'Electron. Ceci est utile pour stocker les accélérateurs dans les fichiers de configuration . + +Exemple: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines cmd+o on Mac and ctrl-o on Window/Linux + myShortcut, err := keys.Parse("Ctrl+Option+A") +``` + +#### Modifier + +Les modificateurs suivants sont des touches qui peuvent être utilisées en combinaison avec la touche accélérateur: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" +const ( + // CmdOrCtrlKey represents Command on Mac and Control on other platforms + CmdOrCtrlKey Modifier = "cmdorctrl" + // OptionOrAltKey represents Option on Mac and Alt on other platforms + OptionOrAltKey Modifier = "optionoralt" + // ShiftKey represents the shift key on all systems + ShiftKey Modifier = "shift" + // ControlKey represents the control key on all systems + ControlKey Modifier = "ctrl" +) +``` + +Un certain nombre de méthodes d'aide sont disponibles pour créer des accélérateurs en utilisant des modificateurs: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" +func CmdOrCtrl(key string) *Accelerator +func OptionOrAlt(key string) *Accelerator +func Shift(key string) *Accelerator +func Control(key string) *Accelerator +``` + +Les modificateurs peuvent être combinés en utilisant `keys.Combo(key string, modifier1 Modifier, modifier2 Modifier, rest ...Modifier)`: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines "Ctrl+Option+A" on Mac and "Ctrl+Alt+A" on Window/Linux + myShortcut := keys.Combo("a", ControlKey, OptionOrAltKey) +``` + +### Type + +Chaque lien de menu doit avoir un type et il y a 5 types disponibles: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +const ( + TextType Type = "Text" + SeparatorType Type = "Separator" + SubmenuType Type = "Submenu" + CheckboxType Type = "Checkbox" + RadioType Type = "Radio" +) +``` + +Pour plus de commodité, des méthodes d'aide sont fournies pour créer rapidement un lien de menu : + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func Text(label string, accelerator *keys.Accelerator, click Callback) *MenuItem +func Separator() *MenuItem +func Radio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func Checkbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func SubMenu(label string, menu *Menu) *Menu +``` + +Vous pouvez également créer des liens directement dans un menu en utilisant les méthodes "Add" : + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func (m *Menu) AddText(label string, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddSeparator() *MenuItem +func (m *Menu) AddRadio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddCheckbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddSubMenu(label string, menu *Menu) *MenuI +``` + +Une note sur les groupes radio : Un groupe radio est défini comme un certain nombre d'éléments du menu radio qui sont à côté l'un de l'autre dans le menu. Cela signifie que vous n'avez pas besoin de regrouper les éléments car il est automatique. Cependant, cela signifie également que vous ne pouvez pas avoir 2 groupes radio les uns à côté des autres - il doit y avoir un élément non-radio entre eux. + +### Callback + +Chaque lien de menu peut avoir une fonction qui est exécutée lorsque l'élément est cliqué : + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +type Callback func(*CallbackData) + +type CallbackData struct { + MenuItem *MenuItem +} +``` + +La fonction reçoit une structure `CallbackData` qui indique quel élément de menu a été cliqué. Ceci est utile lorsque utilise des groupes radio qui peuvent partager une fonction. + +### Role + +:::info Roles + +Les rôles ne sont actuellement pris en charge que sur Mac. + +::: + +Un lien de menu peut avoir un rôle, qui est essentiellement un lien de menu prédéfini. Nous supportons actuellement les rôles suivants : + +| Role | Description | +| ------------ | ----------------------------------------------------------------------------------- | +| AppMenuRole | Le menu standard de l'application Mac. Peut être créé en utilisant `menu.AppMenu()` | +| EditMenuRole | Le menu d'édition standard pour Mac. Peut être créé en utilisant `menu.EditMenu()` | diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx new file mode 100644 index 00000000000..a80e3526732 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx @@ -0,0 +1,853 @@ +--- +sidebar_position: 3 +--- + +# Options + +## Options de l'application + +La structure `Options.App` contient la configuration de l'application. Il est passé à la méthode `wails.Run()`: + +```go title="Example" +import ( + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/linux" + "github.com/wailsapp/wails/v2/pkg/options/mac" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +func main() { + + err := wails.Run(&options.App{ + Title: "Menus Demo", + Width: 800, + Height: 600, + DisableResize: false, + Fullscreen: false, + WindowStartState: options.Maximised, + Frameless: true, + MinWidth: 400, + MinHeight: 400, + MaxWidth: 1280, + MaxHeight: 1024, + StartHidden: false, + HideWindowOnClose: false, + BackgroundColour: &options.RGBA{R: 0, G: 0, B: 0, A: 255}, + AlwaysOnTop: false, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: assetsHandler, + Middleware: assetsMidldeware, + }, + Menu: app.applicationMenu(), + Logger: nil, + LogLevel: logger.DEBUG, + LogLevelProduction: logger.ERROR, + OnStartup: app.startup, + OnDomReady: app.domready, + OnShutdown: app.shutdown, + OnBeforeClose: app.beforeClose, + CSSDragProperty: "--wails-draggable", + CSSDragValue: "drag", + EnableDefaultContextMenu: false, + EnableFraudulentWebsiteDetection: false, + ZoomFactor: 1.0, + IsZoomControlEnabled: false, + Bind: []interface{}{ + app, + }, + ErrorFormatter: func(err error) any { return err.Error() }, + Windows: &windows.Options{ + WebviewIsTransparent: false, + WindowIsTranslucent: false, + BackdropType: windows.Mica, + DisableWindowIcon: false, + DisableFramelessWindowDecorations: false, + WebviewUserDataPath: "", + WebviewBrowserPath: "", + Theme: windows.SystemDefault, + CustomTheme: &windows.ThemeSettings{ + DarkModeTitleBar: windows.RGB(20, 20, 20), + DarkModeTitleText: windows.RGB(200, 200, 200), + DarkModeBorder: windows.RGB(20, 0, 20), + LightModeTitleBar: windows.RGB(200, 200, 200), + LightModeTitleText: windows.RGB(20, 20, 20), + LightModeBorder: windows.RGB(200, 200, 200), + }, + // User messages that can be customised + Messages *windows.Messages + // OnSuspend is called when Windows enters low power mode + OnSuspend func() + // OnResume is called when Windows resumes from low power mode + OnResume func(), + WebviewGpuDisabled: false, + }, + Mac: &mac.Options{ + TitleBar: &mac.TitleBar{ + TitlebarAppearsTransparent: true, + HideTitle: false, + HideTitleBar: false, + FullSizeContent: false, + UseToolbar: false, + HideToolbarSeparator: true, + }, + Appearance: mac.NSAppearanceNameDarkAqua, + WebviewIsTransparent: true, + WindowIsTranslucent: false, + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + Linux: &linux.Options{ + Icon: icon, + WindowIsTranslucent: false, + WebviewGpuPolicy: linux.WebviewGpuPolicyAlways, + ProgramName: "wails" + }, + Debug: options.Debug{ + OpenInspectorOnStartup: false, + }, + }) + + if err != nil { + log.Fatal(err) + } +} + +``` + +### Title + +Le texte affiché dans la barre de titre de la fenêtre. + +Nom : Title
Type : `string` + +### Width + +La largeur initiale de la fenêtre. + +Nom: Width
Type: `int`
Défaut: 1024. + +### Height + +La hauteur initiale de la fenêtre. + +Nom: Height
Type: `int`
Défaut: 768 + +### DisableResize + +Par défaut, la fenêtre principale est redimensionnable. Mettre ceci à `true` le conservera une taille fixe. + +Nom: DisableResize
Type: `bool` + +### Fullscreen + +Obsolète: Veuillez utiliser [WindowStartState](#windowstartstate). + +### WindowStartState + +Définit comment la fenêtre devrait se présenter au démarrage. + +| Valeur | Win | Mac | Lin | +| ---------- | --- | --- | --- | +| Fullscreen | ✅ | ✅ | ✅ | +| Maximised | ✅ | ✅ | ✅ | +| Minimised | ✅ | ❌ | ✅ | + +Nom: WindowStartState
Type: `options.WindowStartState` + +### Frameless + +Quand réglé sur `true`, la fenêtre n'aura pas de bordure ou de barre de titre. Voir aussi les [fenêtres sans cadre sous Windows](../guides/frameless.mdx). + +Nom: Frameless
Type: `bool` + +### MinWidth + +Définit la largeur minimale de la fenêtre. Si la valeur donnée dans `Width` est inférieure à cette valeur, la fenêtre sera définie à `MinWidth` par défaut. + +Nom: MinWidth
Type: `int` + +### MinHeight + +Définit la hauteur minimale de la fenêtre. Si la valeur donnée dans `Height` est inférieure à cette valeur, la fenêtre sera définie à `MinHeight` par défaut. + +Nom: MinHeight
Type: `int` + +### MaxWidth + +Définit la largeur maximale de la fenêtre. Si la valeur donnée dans `Width` est supérieure à cette valeur, la fenêtre sera définie à `MaxWidth` par défaut. + +Nom: MaxWidth
Type: `int` + +### MaxHeight + +Définit la hauteur maximale de la fenêtre. Si la valeur donnée en `Height` est supérieure à cette valeur, la fenêtre sera définie à `MaxHeight` par défaut. + +Nom: MaxHeight
Type: `int` + +### StartHidden + +Lorsque réglé sur `true`, l'application sera masquée jusqu'à ce que [WindowShow](../reference/runtime/window.mdx#windowshow) soit appelé. + +Nom: StartHidden
Type: `bool` + +### HideWindowOnClose + +Par défaut, la fermeture de la fenêtre fermera l'application. Définir ceci à `true` signifie que + +la fenêtre sera cachée à la place. + +Nom: HideWindowOnClose
Type: `bool` + +### BackgroundColour + +Cette valeur est la couleur de fond par défaut de la fenêtre. Exemple: options.NewRGBA(255,0,0,128) - Rouge à 50% de transparence + +Nom: BackgroundColour
Type: `*options.RGBA`
Défaut: white + +### AlwaysOnTop + +Indique que la fenêtre doit rester au-dessus des autres fenêtres lors de la perte de focus. + +Nom: AlwaysOnTop
Type: `bool` + +### Assets + +Obsolète: Veuillez utiliser des actifs sur les options [AssetServer spécifiques](#assetserver). + +### AssetsHandler + +Obsolète : Veuillez utiliser AssetsHandler sur [Options spécifiques à AssetServer](#assetserver). + +### AssetServer + +Ceci définit les options spécifiques à AssetServer. Il permet de personnaliser l'AssetServer avec des actifs statiques, servant les assets dynamiquement avec un `http.Handler` ou brancher dans la chaîne de requêtes avec un `assetserver.Middleware`. + +Toutes les fonctionnalités d'une `http.Request` ne sont pas actuellement prises en charge, veuillez consulter la matrice de fonctionnalité suivante : + +| Fonctionalité | Win | Mac | Lin | +| ----------------------- | --- | --- | ------ | +| GET | ✅ | ✅ | ✅ | +| POST | ✅ | ✅ | ✅ [^1] | +| PUT | ✅ | ✅ | ✅ [^1] | +| PATCH | ✅ | ✅ | ✅ [^1] | +| DELETE | ✅ | ✅ | ✅ [^1] | +| Request Headers | ✅ | ✅ | ✅ [^1] | +| Request Body | ✅ | ✅ | ✅ [^2] | +| Request Body Streaming | ✅ | ✅ | ✅ [^2] | +| Response StatusCodes | ✅ | ✅ | ✅ [^1] | +| Response Headers | ✅ | ✅ | ✅ [^1] | +| Response Body | ✅ | ✅ | ✅ | +| Response Body Streaming | ❌ | ✅ | ✅ | +| WebSockets | ❌ | ❌ | ❌ | +| HTTP Redirects 30x | ✅ | ❌ | ❌ | + +Nom: AssetServer
Type: `*assetserver.Options` + +#### Assets + +Les ressources statiques du frontend à être utilisées par l'application. + +Une requête GET est d'abord tentée d'être servie à partir de ce `fs.FS`. Si le `fs.FS` retourne `os. rrNotExist` pour ce fichier, le traitement des requêtes va revenir au [Handler](#handler) et essaie de répondre à la requête GET. + +Si la valeur est nulle, toutes les requêtes GET seront envoyées à [Handler](#handler). + +Nom: Assets
Type: `fs.FS` + +#### Handler + +Le gestionnaire d'assets est un `http.Handler` générique pour la gestion de secours des assets qui ne peuvent pas être trouvés. + +Le gestionnaire sera appelé pour chaque requête GET qui ne peut pas être servie à partir de [Assets](#assets), en raison de `os.ErrNotExist`. De plus, toutes les requêtes non GET seront toujours servies par ce gestionnaire. Si non défini, le résultat est le suivant dans les cas où le Gestionnaire aurait été appelé : + +- Requête GET : `http.StatusNotFound` +- Autre requête : `http.StatusMethodNotAllowed` + +REMARQUE : Lorsqu'il est utilisé en combinaison avec un serveur de développement Frontend, il peut y avoir des limitations, par exemple. Vite affiche l'index.html sur chaque chemin qui ne contient pas d'extension de fichier. + +Nom: AssetsHandler
Type: `http.Handler` + +#### Middleware + +Middleware est un Middleware HTTP qui permet de se connecter à la chaîne de requêtes AssetServer. Il permet de sauter dynamiquement le gestionnaire de requête par défaut, par exemple implémenter un routage spécialisé, etc. Le Middleware est appelé pour construire un nouveau `http.Handler` utilisé par l'AssetSever et reçoit également le gestionnaire par défaut utilisé par le serveur AssetServer comme argument. + +Si elle n'est pas définie, la chaîne de requête AssetServer par défaut est exécutée. + +Nom: Middleware
Type: `assetserver.Middleware` + +### Menu + +Le menu à utiliser par l'application. Plus de détails sur les menus dans la [Référence des Menu](../reference/runtime/menu.mdx). + +:::note + +Sur Mac, si aucun menu n'est spécifié, un menu par défaut sera créé. + +::: + +Nom: Menu
Type: `*menu.Menu` + +### Logger + +Le logger à utiliser par l'application. Plus de détails sur la connexion dans la [Référence du logger](../reference/runtime/log.mdx). + +Nom: Logger
Type: `logger.Logger`
Défaut: Logs envoyé à Stdout + +### LogLevel + +Le niveau de log par défaut. Plus de détails sur la connexion dans la [Référence du logger](../reference/runtime/log.mdx). + +Nom: LogLevel
Type: `logger.LogLevel`
Défaut: `Info` en mode dev, `Error` en mode production + +### LogLevelProduction + +Le niveau de log par défaut pour les compilations de production. Plus de détails sur la connexion dans la [Référence du logger](../reference/runtime/log.mdx). + +Nom: LogLevelProduction
Type: `logger.LogLevel`
Défaut: `Error` + +### OnStartup + +Ce callback est appelé après la création du frontend, mais avant que `index.html` n'ait été chargé. Il lui donne le contexte de l'application. + +Nom: OnStartup
Type: `func(ctx context.Context)` + +### OnDomReady + +Ce callback est appelé après que le frontend ait chargé `index.html` et ses ressources. Il lui donne le contexte de l'application. + +Nom: OnDomReady
Type: `func(ctx context.Context)` + +### OnShutdown + +Ce calllback est appelé après que le frontend ait été détruit, juste avant la fin de l'application. Il lui donne le contexte de l'application. + +Nom: OnShutdown
Type: `func(ctx context.Context)` + +### OnBeforeClose + +Si ce callback est défini, il sera appelé lorsque l'application est sur le point de quitter, soit en cliquant sur la fenêtre fermez le bouton ou en appelant `runtime.Quit`. Retourner "true" dans cette méthode entraînera la poursuite de l'application, "false" continuera à éteindre comme d'habitude. C'est un bon exemple pour confirmer avec l'utilisateur si il souhaite quitter le programme. + +Exemple: + +```go title=windowsapp.go +func (b *App) beforeClose(ctx context.Context) (prevent bool) { + dialog, err := runtime.MessageDialog(ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Quit?", + Message: "Are you sure you want to quit?", + }) + + if err != nil { + return false + } + return dialog != "Yes" +} +``` + +Nom: OnBeforeClose
Type: `func(ctx context.Context) bool` + +### CSSDragProperty + +Indique la propriété CSS à utiliser pour identifier quels éléments peuvent être utilisés pour faire glisser la fenêtre. Par défaut : `--wails-draggable`. + +Nom: CSSDragProperty
Type: `string` + +### CSSDragValue + +Indique quelle valeur le style `CSSDragProperty` doit avoir pour faire glisser la fenêtre. Par défaut: `drag`. + +Nom: CSSDragValue
Type: `string` + +### EnableDefaultContextMenu + +EnableDefaultContextMenu active le menu contextuel par défaut du navigateur en production. + +By default, the browser's default context-menu is only available in development and in a `-debug` [build](../reference/cli.mdx#build) along with the devtools inspector, Using this option you can enable the default context-menu in `production` while the devtools inspector won't be available unless the `-devtools` build flag is used. + +Lorsque cette option est activée, par défaut, le menu contextuel ne sera affiché que pour du texte (où Couper/Copier/Coller est nécessaire), pour remplacer ce comportement, vous pouvez utiliser la propriété CSS `--default-contextmenu` sur n'importe quel élément HTML (y compris le corps ``) avec les valeurs suivantes : + +| Style CSS | Comportement | +| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--default-contextmenu: auto;` | (**défaut**) n'affichera le menu contextuel par défaut que si :
contentEditable est vrai OU le texte a été sélectionné OU l'élément est entrée ou la zone de texte | +| `--default-contextmenu: show;` | affichera toujours le menu de contexte par défaut | +| `--default-contextmenu: hide;` | masquera toujours le menu contextuel par défaut | + +Cette règle est héritée comme n'importe quelle règle CSS normale, donc l'imbrication fonctionne comme prévu. + +:::note +Cette fonctionnalité de filtrage n'est activée qu'en production, donc en développement et en construction de débogage, le menu contextuel complet est toujours disponible partout. +::: + +:::warning +Cette fonctionnalité de filtrage n'est PAS une mesure de sécurité, le développeur devrait s'attendre à ce que le menu contextuel complet puisse être divulgué à tout moment qui pourrait contenir des commandes comme (Télécharger l'image, Recharger, Enregistrer la page web), si c'est une préoccupation, le développeur DEVRAIT NE PAS activer le menu contextuel par défaut. +::: + + +Nom: EnableDefaultContextMenu
Type: `bool` + +### EnableFraudulentWebsiteDetection + +EnableFraudulentWebWebDetection permet de rechercher des contenus frauduleux, tels que des programmes malveillants ou des tentatives d'hameçonnage. Ces services peuvent envoyer des informations à partir de votre application, telles que les URL vers lesquelles vous avez navigué et éventuellement d'autres contenus vers le cloud, des services d'Apple et de Microsoft. + +Nom: EnableFraudulentWebsiteDetection
Type: `bool` + +### ZoomFactor + +Nom: ZoomFactor
Type: `float64` + +Ceci définit le facteur de zoom pour WebView2. Il s'agit de l'option correspondant au zoom avant ou arrière défini par l'utilisateur. + +### IsZoomControlEnabled + +Nom : IsZoomControlEnabled
Type : `bool` + +Cela permet de modifier le facteur de zoom par l'utilisateur. Veuillez noter que le facteur de zoom peut être défini dans les options tandis que ne permet pas à l'utilisateur de le modifier à l'exécution (f.e. pour une application vitrine ou similaire). + +### Bind + +La liste des structs Go définissant des méthodes qui doivent être liées au frontend. + +Nom: Bind
Type: `[]interface{}` + +### ErrorFormatter + +Une fonction qui détermine comment les erreurs sont formatées lorsqu'elles sont retournées par un appel de méthode JS-to-Go. La valeur retournée sera sous format JSON. + +Nom: ErrorFormatter
Type: `func (error) any` + +### Windows + +Ceci définit les options [spécifiques à Windows](#windows). + +Nom: Windows
Type: `*windows.Options` + +#### WebviewIsTransparent + +Mettre ceci à `true` rendra l'arrière-plan du webview transparent quand une valeur alpha de `0` est utilisée. Cela signifie que si vous utilisez `rgba(0,0,0,0)` pour `la couleur d'arrière-plan` dans votre CSS, la fenêtre d'hôte sera affichée. Souvent combiné avec [WindowIsTranslucent](#WindowIsTranslucent) pour faire des applications d'apparence de givre. + +Nom : WebviewIsTransparent
Type : `bool` + +#### WindowIsTranslucent + +Définir ceci à `true` rendra l'arrière-plan de la fenêtre translucide. Souvent combiné avec [WebviewIsTransparent](#WebviewIsTransparent). + +Pour les versions de Windows 11 avant la version 22621, cela utilisera la méthode [BlurBehind](https://learn.microsoft.com/en-us/windows/win32/dwm/blur-ovw) pour la translucidité, qui peut être lente. Pour les versions de Windows 11 après la version 22621, cela activera les nouveaux types de transparence qui sont beaucoup plus rapides. Par défaut, le type de transparence utilisé sera déterminé par Windows. Pour configurer ceci, utilisez l'option [BackdropType](#BackdropType). + +Nom: WindowIsTranslucent
Type: `bool` + +#### BackdropType + +:::note + +Nécessite Windows 11 version 22621 ou supérieure. + +::: + +Définit le type de transparence de la fenêtre. Ceci n'est applicable que si [WindowIsTranslucent](#WindowIsTranslucent) est défini à `true`. + +Nom: BackdropType
Type `windows.BackdropType` + +La valeur peut être l'une des valeurs suivantes : + +| Valeur | Description | +| ------- | ------------------------------------------------------------------------------------------------- | +| Auto | Laisser Windows décider quel arrière-plan utiliser | +| None | Ne pas utiliser de transparence | +| Acrylic | Utilisez l'effet [Acrylique](https://learn.microsoft.com/en-us/windows/apps/design/style/acrylic) | +| Mica | Utiliser l'effet [Mica](https://learn.microsoft.com/en-us/windows/apps/design/style/mica) | +| Tabbed | Utiliser Tabbed. C'est un arrière-plan qui est similaire à Mica. | + +#### DisableWindowIcon + +Définir ceci à `true` supprimera l'icône dans le coin supérieur gauche de la barre de titre. + +Nom: DisableWindowIcon
Type: `bool` + +#### DisableFramelessWindowDecorations + +Définir ceci à `true` supprimera les décorations de fenêtre en mode [sans cadre](#Frameless). Cela signifie qu'il n'y aura pas de « Aero Shadow» et aucun « Coins arrondis» ne sera affiché pour la fenêtre. Veuillez noter que les "coins arrondis" ne sont pris en charge que sur Windows 11. + +Nom: DisableFramelessWindowDecorations
Type: `bool` + +#### WebviewUserDataPath + +Ceci définit le chemin où WebView2 stocke les données de l'utilisateur. Si vide, `%APPDATA%\[BinaryName.exe]` sera utilisé. + +Nom: WebviewUserDataPath
Type: `string` + +#### WebviewBrowserPath + +Ceci définit le chemin vers un répertoire avec les fichiers exécutables et bibliothèques WebView2. Si l'option est vide, l'instance de webview2 installé dans le système sera utilisé. + +Informations importantes sur la version corrigée : + +- [Comment récupérer et extraire l'exécutable](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#details-about-the-fixed-version-runtime-distribution-mode) +- [Problèmes connus pour la version corrigée](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#known-issues-for-fixed-version) +- [Le chemin de la version corrigée du runtime WebView2 ne doit pas contenir \Edge\Application\.](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.1245.22#createcorewebview2environmentwithoptions) + +Nom: WebviewBrowserPath
Type: `string` + +#### Theme + +Version minimale de Windows : Windows 10 2004/20H1 + +Ceci définit le thème que l'application doit utiliser : + +| Valeur | Description | +| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| SystemDefault | _Default_. Le thème sera basé sur la valeur par défaut du système. Si l'utilisateur change de thème, l'application se mettra à jour pour utiliser le nouveau paramètre | +| Dark | L'application utilisera uniquement un thème sombre | +| Light | L'application utilisera uniquement un thème clair | + +Nom: Theme
Type: `windows.Theme` + +#### CustomTheme + +:::note + +Version minimale de Windows : Windows 10/11 2009/21H2 Build 22000 + +::: + +Vous permet de spécifier des couleurs personnalisées pour la barre de titre, le texte de titre et la bordure pour le mode clair et foncé. ainsi que lorsque la fenêtre est active ou inactive. + +Nom: CustomTheme
Type: `windows.CustomTheme` + +##### Type CustomTheme + +Le struct CustomTheme utilise `int32` pour spécifier les valeurs de couleurs. Celles-ci sont au format standard(!) Windows soit : `0x00BBGGAA`. Une fonction d'aide est fournie pour effectuer les conversions de RGB dans ce format : `windows.RGB(r,g,b uint8)`. + +NOTE : Toute valeur non fournie sera par défaut noire. + +```go +type ThemeSettings struct { + DarkModeTitleBar int32 + DarkModeTitleBarInactive int32 + DarkModeTitleText int32 + DarkModeTitleTextInactive int32 + DarkModeBorder int32 + DarkModeBorderInactive int32 + LightModeTitleBar int32 + LightModeTitleBarInactive int32 + LightModeTitleText int32 + LightModeTitleTextInactive int32 + LightModeBorder int32 + LightModeBorderInactive int32 +} +``` + +Exemple: + +```go + CustomTheme: &windows.ThemeSettings{ + // Theme to use when window is active + DarkModeTitleBar: windows.RGB(255, 0, 0), // Red + DarkModeTitleText: windows.RGB(0, 255, 0), // Green + DarkModeBorder: windows.RGB(0, 0, 255), // Blue + LightModeTitleBar: windows.RGB(200, 200, 200), + LightModeTitleText: windows.RGB(20, 20, 20), + LightModeBorder: windows.RGB(200, 200, 200), + // Theme to use when window is inactive + DarkModeTitleBarInactive: windows.RGB(128, 0, 0), + DarkModeTitleTextInactive: windows.RGB(0, 128, 0), + DarkModeBorderInactive: windows.RGB(0, 0, 128), + LightModeTitleBarInactive: windows.RGB(100, 100, 100), + LightModeTitleTextInactive: windows.RGB(10, 10, 10), + LightModeBorderInactive: windows.RGB(100, 100, 100), + }, +``` + +#### Messages + +Un struct de chaînes utilisées par l'installateur webview2 si un runtime webview2 valide n'est pas trouvé. + +Nom: Messages
Type: `*windows.Messages` + +Personnalisez ceci pour n'importe quelle langue que vous choisissez de supporter. + +#### ResizeDebounceMS + +ResizeDebounceMS est le temps entre deux réajustements du contenu de la fenêtre lors du redimensionnement de la fenêtre. La valeur par défaut (0) effectuera des réajustements aussi vite qu'il le peut. + +Nom: ResizeDebounceMS
Type: `uint16` + +#### OnSuspend + +Si défini, cette fonction sera appelée lorsque Windows passera en mode économie d'énergie + +Nom: OnSuspend
Type: `func()` + +#### OnResume + +Si défini, cette fonction sera appelée lorsque Windows sortira du mode économie d'énergie + +Nom: OnResume
Type: `func()` + +#### WebviewGpuIsDisabled + +Définir ceci à `true` désactivera l'accélération matérielle GPU pour la webview. + +Nom: WebviewGpuIsDisabled
Type: `bool` + +#### EnableSwipeGestures + +Setting this to `true` will enable swipe gestures for the webview. + +Name: EnableSwipeGestures
Type: `bool` + +### Mac + +Ceci définit [les options spécifiques à Mac](#mac). + +Nom: Mac
Type: `*mac.Options` + +#### TitleBar + +La structure TitleBar permet de configurer l'apparence de la barre de titre. + +Nom: TitleBar
Type: [`*mac.TitleBar`](#titlebar-struct) + +##### Struct de la Titlebar + +La barre de titre de l'application peut être personnalisée en utilisant les options suivantes de TitleBar : + +```go +type TitleBar struct { + TitlebarAppearsTransparent bool + HideTitle bool + HideTitleBar bool + FullSizeContent bool + UseToolbar bool + HideToolbarSeparator bool +} +``` + +| Nom | Description | +| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| TitlebarAppearsTransparent | Rend la barre de titre transparente. Cela a pour effet de masquer la barre de titre et le contenu remplit la fenêtre. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindow/1419167-titlebarappearstransparent?language=objc) | +| HideTitle | Masque le titre de la fenêtre. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindowtitlevisibility?language=objc) | +| HideTitleBar | Supprime [NSWindowStyleMaskTitled](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemasktitled/) du style | +| FullSizeContent | Fait que la webview remplisse toute la fenêtre. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemaskfullsizecontentview) | +| UseToolbar | Ajoute une barre d'outils par défaut à la fenêtre. [Apple Docs](https://developer.apple.com/documentation/appkit/nstoolbar?language=objc) | +| HideToolbarSeparator | Supprime la ligne située sous la barre d'outils. [Apple Docs](https://developer.apple.com/documentation/appkit/nstoolbar/1516954-showsbaselineseparator?language=objc) | + +Des paramètres préconfigurés sont disponibles : + +| Configuration | Exemple | +| --------------------------- | ---------------------------------------------- | +| `mac.TitleBarDefault()` | ![](/img/reference/titlebar-default.webp) | +| `mac.TitleBarHidden()` | ![](/img/reference/titlebar-hidden.webp) | +| `mac.TitleBarHiddenInset()` | ![](/img/reference/titlebar-hidden-inset.webp) | + +Exemple: + +```go +Mac: &mac.Options{ + TitleBar: mac.TitleBarHiddenInset(), +} +``` + +Cliquez sur [ici](https://github.com/lukakerr/NSWindowStyles) si vous voulez de l'inspiration sur la personnalisation de la barre de titre. + +#### Appearance + +L'apparence est utilisée pour définir le style de votre application en accord avec les noms [NSAppearance](https://developer.apple.com/documentation/appkit/nsappearancename?language=objc) d'Apple. + +Nom: Appearance
Type: [`mac.AppearanceType`](#appearance-type) + +##### Type d'Appearance + +Vous pouvez spécifier l'apparence [de l'application](https://developer.apple.com/documentation/appkit/nsappearance?language=objc). + +| Valeur | Description | +| ----------------------------------------------------- | ------------------------------------------------------------------- | +| DefaultAppearance | DefaultAppararance utilise la valeur système par défaut | +| NSAppearanceNameAqua | Utilise l'apparence thème clair standard | +| NSAppearanceNameDarkAqua | Utilise l'apparence thème sombre standard | +| NSAppearanceNameVibrantLight | Utilise une apparence avec une lumière vibrante | +| NSAppearanceNameAccessibilityHighContrastAqua | Utilise l'apparence thème clair standard avec un constrate élevé | +| NSAppearanceNameAccessibilityHighContrastDarkAqua | Utilise l'apparence thème sombre standard avec un contraste élevé | +| NSAppearanceNameAccessibilityHighContrastVibrantLight | Utilise l'apparence lumière vibrante avec un constrate élevé | +| NSAppearanceNameAccessibilityHighContrastVibrantDark | Utilise l'apparence du thème sombre vibrant avec un constrate élevé | + +Exemple: + +```go +Mac: &mac.Options{ + Appearance: mac.NSAppearanceNameDarkAqua, +} +``` + +#### WebviewIsTransparent + +Mettre ceci à `true` rendra l'arrière-plan du webview transparent quand une valeur alpha de `0` est utilisée. Cela signifie que si vous utilisez `rgba(0,0,0,0)` pour `la couleur d'arrière-plan` dans votre CSS, la fenêtre d'hôte sera affichée. Souvent combiné avec [WindowIsTranslucent](#WindowIsTranslucent) pour faire des applications d'apparence de givre. + +Nom : WebviewIsTransparent
Type : `bool` + +#### WindowIsTranslucent + +Définir ceci à `true` rendra l'arrière-plan de la fenêtre translucide. Souvent combiné avec [WebviewIsTransparent](#WebviewIsTransparent) pour donner un aspect givré à la fenêtre. + +Nom: WindowIsTranslucent
Type: `bool` + +#### Preferences + +The Preferences struct provides the ability to configure the Webview preferences. + +Name: Preferences
Type: [`*mac.Preferences`](#preferences-struct) + +##### Preferences struct + +You can specify the webview preferences. + +```go +type Preferences struct { + TabFocusesLinks u.Bool + TextInteractionEnabled u.Bool + FullscreenEnabled u.Bool +} +``` + +| Nom | Description | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| TabFocusesLinks | A Boolean value that indicates whether pressing the tab key changes the focus to links and form controls. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/2818595-tabfocuseslinks?language=objc) | +| TextInteractionEnabled | A Boolean value that indicates whether to allow people to select or otherwise interact with text. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3727362-textinteractionenabled?language=objc) | +| FullscreenEnabled | A Boolean value that indicates whether a web view can display content full screen. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3917769-elementfullscreenenabled?language=objc) | + +Exemple: + +```go +Mac: &mac.Options{ + Preferences: &mac.Preferences{ + TabFocusesLinks: mac.Enabled, + TextInteractionEnabled: mac.Disabled, + FullscreenEnabled: mac.Enabled, + } +} +``` + +#### About + +Cette configuration vous permet de définir le titre, le message et l'icône pour l'élément de menu "À propos" dans le menu de l'application créé par le rôle "AppMenu". + +Nom: About
Type: [`*mac.AboutInfo`](#about-struct) + +##### Struct de About + +```go + +type AboutInfo struct { + Title string + Message string + Icon []byte +} +``` + +Si ces paramètres sont fournis, un lien de menu "À propos" apparaîtra dans le menu de l'application (lors de l'utilisation du rôle `AppMenu`). Exemple: + +```go +//go:embed build/appicon.png +var icon []byte + +func main() { + err := wails.Run(&options.App{ + ... + Mac: &mac.Options{ + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + }) +``` + +L'élément de menu "À propos" apparaîtra dans le menu de l'application: + +```mdx-code-block +
+ +
+
+``` + +Lorsqu'il est cliqué, cela ouvrira la boîte de message "à propos" : + +```mdx-code-block +
+ +
+
+``` + +### Linux + +Ceci définit [les options spécifiques à Linux](#linux). + +Nom: Linux
Type: `*linux.Options` + +#### Icon + +Définit l'icône représentant la fenêtre. Cette icône est utilisée lorsque la fenêtre est réduite (aussi appelée iconified). + +Nom: Icon
Type: `[]byte` + +Certains gestionnaires de fenêtres ou environnements de bureau peuvent également le placer dans le cadre de la fenêtre, ou l'afficher dans d'autres contextes. Sur d'autres, l'icône n'est pas du tout utilisée, donc son utilisation peut varier. + +NOTE : Gnome sur Wayland n'affiche pas cette icône. Pour y avoir une icône d'application, un fichier `.desktop` doit être utilisé. Sous KDE, cela devrait fonctionner. + +L’icône doit être fournie dans la taille qu’elle a été dessinée naturellement, c’est-à-dire ne pas redimensionner l’image avant de la passer. La mise à l'échelle est reportée à la dernière minute, lorsque la taille finale désirée est connue, pour permettre une meilleure qualité. + +#### WindowIsTranslucent + +Définir ceci à `true` rendra l'arrière-plan de la fenêtre translucide. Certains gestionnaires de fenêtres peuvent l'ignorer, ou résulter en une fenêtre noire. + +Nom: WindowIsTranslucent
Type: `bool` + +#### WebviewGpuPolicy + +Cette option est utilisée pour déterminer la politique d'accélération matérielle effectuée par webview. + +Nom: WebviewGpuPolicy
Type: [`options.WebviewGpuPolicy`](#webviewgpupolicy-type)
Défaut: `WebviewGpuPolicyAlways` + +##### Type de WebviewGpuPolicy + +| Valeur | Description | +| ------------------------ | ---------------------------------------------------------------------------- | +| WebviewGpuPolicyAlways | L'accélération matérielle est toujours activée | +| WebviewGpuPolicyOnDemand | L'accélération matérielle est activée/désactivée à la demande du contenu web | +| WebviewGpuPolicyNever | L'accélération matérielle est toujours désactivée | + +#### ProgramName + +This option is used to set the program's name for the window manager via GTK's g_set_prgname(). This name should not be localized, [see the docs](https://docs.gtk.org/glib/func.set_prgname.html). + +When a .desktop file is created this value helps with window grouping and desktop icons when the .desktop file's `Name` property differs form the executable's filename. + +Name: ProgramName
Type: string
+ +### Debug + +Ceci définit [les options spécifiques au débogage](#Debug) qui s'appliquent aux compilations de débogage. + +Nom: Debug
Type: `options.Debug` + +#### OpenInspectorOnStartup + +Définir cette option à `true` ouvrira l'inspecteur Web au démarrage de l'application. + +Nom: OpenInspectorOnStartup
Type: `bool` + +[^1]: Cela nécessite la prise en charge de WebKit2GTK 2.36+ et votre application doit être construite avec la balise de compilation `webkit2_36` pour activer le support de cette fonctionnalité. Cela augmente aussi la version minnimale de WebKit2GTK à 2.36 pour votre application. +[^2]: Cela nécessite la prise en charge de WebKit2GTK 2.40+ et votre application doit être construite avec la balise de compilation `webkit2_40` pour activer le support de cette fonctionnalité. Cela augmente aussi la version minnimale de WebKit2GTK à 2.40 pour votre application. [ [ ↩](#fnref2:2){.footnote-backref} ↩](#fnref:2){.footnote-backref} diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx new file mode 100644 index 00000000000..a5f067dd870 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx @@ -0,0 +1,92 @@ +--- +sidebar_position: 5 +--- + +# Configuration du projet + +La configuration du projet se trouve dans le fichier `wails.json` du répertoire du projet. La structure de la configuration est : + +```json5 +{ + // Project config version + "version": "", + // The project name + "name": "", + // Relative path to the directory containing the compiled assets, this is normally inferred and could be left empty + "assetdir": "", + // Additional directories to trigger reloads (comma separated), this is only used for some advanced asset configurations + "reloaddirs": "", + // The directory where the build files reside. Defaults to 'build' + "build:dir": "", + // Relative path to the frontend directory. Defaults to 'frontend' + "frontend:dir": "", + // The command to install node dependencies, run in the frontend directory - often `npm install` + "frontend:install": "", + // The command to build the assets, run in the frontend directory - often `npm run build` + "frontend:build": "", + // This command has been replaced by frontend:dev:build. If frontend:dev:build is not specified will falls back to this command. \nIf this command is also not specified will falls back to frontend:build + "frontend:dev": "", + // This command is the dev equivalent of frontend:build. If not specified falls back to frontend:dev + "frontend:dev:build": "", + // This command is the dev equivalent of frontend:install. If not specified falls back to frontend:install + "frontend:dev:install": "", + // This command is run in a separate process on `wails dev`. Useful for 3rd party watchers or starting 3d party dev servers + "frontend:dev:watcher": "", + // URL to a 3rd party dev server to be used to serve assets, EG Vite. \nIf this is set to 'auto' then the devServerUrl will be inferred from the Vite output + "frontend:dev:serverUrl": "", + // Relative path to the directory that the auto-generated JS modules will be created + "wailsjsdir": "", + // The name of the binary + "outputfilename": "", + // The default time the dev server waits to reload when it detects a change in assets + "debounceMS": 100, + // Address to bind the wails dev sever to. Default: localhost:34115 + "devServer": "", + // Arguments passed to the application in shell style when in dev mode + "appargs": "", + // Defines if build hooks should be run though they are defined for an OS other than the host OS. + "runNonNativeBuildHooks": false, + "preBuildHooks": { + // The command that will be executed before a build of the specified GOOS/GOARCH: ${platform} is replaced with the "GOOS/GOARCH". The "GOOS/GOARCH" hook is executed before the "GOOS/*" and "*/*" hook. + "GOOS/GOARCH": "", + // The command that will be executed before a build of the specified GOOS: ${platform} is replaced with the "GOOS/GOARCH". The "GOOS/*" hook is executed before the "*/*" hook. + "GOOS/*": "", + // The command that will be executed before every build: ${platform} is replaced with the "GOOS/GOARCH". + "*/*": "" + }, + "postBuildHooks": { + // The command that will be executed after a build of the specified GOOS/GOARCH: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. The "GOOS/GOARCH" hook is executed before the "GOOS/*" and "*/*" hook. + "GOOS/GOARCH": "", + // The command that will be executed after a build of the specified GOOS: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. The "GOOS/*" hook is executed before the "*/*" hook. + "GOOS/*": "", + // The command that will be executed after every build: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. + "*/*": "" + }, + // Data used to populate manifests and version info. + "info": { + // The company name. Default: [The project name] + "companyName": "", + // The product name. Default: [The project name] + "productName": "", + // The version of the product. Default: '1.0.0' + "productVersion": "", + // The copyright of the product. Default: 'Copyright.........' + "copyright": "", + // A short comment of the app. Default: 'Built using Wails (https://wails.app)' + "comments": "" + }, + // 'multiple': One installer per architecture. 'single': Single universal installer for all architectures being built. Default: 'multiple' + "nsisType": "", + // Whether the app should be obfuscated. Default: false + "obfuscated": "", + // The arguments to pass to the garble command when using the obfuscated flag + "garbleargs": "" +} +``` + +This file is read by the Wails CLI when running `wails build` or `wails dev`. + +The `assetdir`, `reloaddirs`, `wailsjsdir`, `debounceMS`, `devserver` and `frontenddevserverurl` flags in `wails build/dev` will update the project config +and thus become defaults for subsequent runs. + +The JSON Schema for this file is located [here](https://wails.io/schemas/config.v2.json). diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx new file mode 100644 index 00000000000..ab2da957dd4 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx @@ -0,0 +1,13 @@ +--- +sidebar_position: 7 +--- + +# Navigateur + +Ces méthodes sont liées au navigateur du système. + +### BrowserOpenURL + +Ouvre l'URL donnée dans le navigateur système. + +Go: `BrowserOpenURL(ctx context.Context, url string)`
JS: `BrowserOpenURL(url string)` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx new file mode 100644 index 00000000000..c37399d0bf0 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx @@ -0,0 +1,23 @@ +--- +sidebar_position: 8 +--- + +# Clipboard + +Cette partie du runtime fournit un accès au presse-papiers du système d'exploitation.
L'implémentation actuelle ne gère que le texte. + +### ClipboardGetText + +Cette méthode lit le texte actuellement stocké dans le presse-papiers. + +Go: `ClipboardGetText(ctx context.Context) (string, error)`
Retourne: une chaîne de caractères (si le presse papier est vide, il retournera une chaîne vide) ou une erreur. + +JS: `ClipboardGetText(): Promise`
Retourne : Un promise d'une chaine de caractères (si le presse papier est vide, il retournera une chaîne vide). + +### ClipboardSetText + +Cette méthode écrit du texte dans le presse-papiers. + +Go: `ClipboardSetText(ctx context.Context, text string) error`
Retourne: Une erreur si il y en a une. + +JS: `ClipboardSetText(text: string): Promise`
Retourne: Un promise avec true si le texte a été écrit avec succès dans le presse papier, autrement il contiendra false. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx new file mode 100644 index 00000000000..1bbc6522e0f --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx @@ -0,0 +1,302 @@ +--- +sidebar_position: 5 +--- + +# Boîte de dialogue + +Cette partie du runtime fournit un accès aux boîtes de dialogue natives, telles que les sélecteurs de fichiers et les boîtes de messages. + +:::info JavaScript + +La boîte de dialogue n'est actuellement pas prise en charge dans l'exécuteur JS. + +::: + +### OpenDirectoryDialog + +Ouvre une boîte de dialogue qui invite l'utilisateur à sélectionner un répertoire. Peut être personnalisé en utilisant [OpenDialogOptions](#opendialogoptions). + +Go: `OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)` + +Renvoie : le répertoire sélectionné (vide si l'utilisateur a annulé) ou une erreur + +### OpenFileDialog + +Ouvre une boîte de dialogue qui invite l'utilisateur à sélectionner un fichier. Peut être personnalisé en utilisant [OpenDialogOptions](#opendialogoptions). + +Go: `OpenFileDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)` + +Renvoie : le fichier sélectionné (vide si l'utilisateur a annulé) ou une erreur + +### OpenFileDialog + +Ouvre une boîte de dialogue qui invite l'utilisateur à sélectionner plusieurs fichiers. Peut être personnalisé en utilisant [OpenDialogOptions](#opendialogoptions). + +Go: `OpenMultipleFilesDialog(ctx context.Context, dialogOptions OpenDialogOptions) ([]string, error)` + +Renvoie : les fichiers sélectionnés (nil si l'utilisateur a annulé) ou une erreur + +### SaveFileDialog + +Ouvre une boîte de dialogue qui invite l'utilisateur à saisir un nom pour le fichier à enregistrer. Peut être personnalisé en utilisant [SaveDialogOptions](#savedialogoptions). + +Go: `SaveFileDialog(ctx context.Context, dialogOptions SaveDialogOptions) (string, error)` + +Renvoie : le fichier sélectionné (vide si l'utilisateur a annulé) ou une erreur + +### MessageDialog + +Affiche un message en utilisant une boîte de dialogue. Peut être personnalisé en utilisant [MessageDialogOptions](#messagedialogoptions). + +Go: `MessageDialog(ctx context.Context, dialogOptions MessageDialogOptions) (string, error)` + +Renvoie : Le texte du bouton sélectionné ou une erreur + +## Options + +### OpenDialogOptions + +```go +type OpenDialogOptions struct { + DefaultDirectory string + DefaultFilename string + Title string + Filters []FileFilter + ShowHiddenFiles bool + CanCreateDirectories bool + ResolvesAliases bool + TreatPackagesAsDirectories bool +} +``` + +| Champ | Description | Win | Mac | Lin | +| -------------------------- | -------------------------------------------------------------- | --- | --- | --- | +| DefaultDirectory | Le répertoire que la boîte de dialogue affichera à l'ouverture | ✅ | ✅ | ✅ | +| DefaultFilename | Le nom du fichier par défaut | ✅ | ✅ | ✅ | +| Title | Titre pour la boite de dialogue | ✅ | ✅ | ✅ | +| [Filters](#filefilter) | Une liste de filtres de fichiers | ✅ | ✅ | ✅ | +| ShowHiddenFiles | Afficher les fichiers cachés par le système | | ✅ | ✅ | +| CanCreateDirectories | Autoriser l'utilisateur de créer des dossiers | | ✅ | | +| ResolvesAliases | Si vrai, retourne le fichier et non l'alias | | ✅ | | +| TreatPackagesAsDirectories | Autoriser la navigation dans les dossiers | | ✅ | | + +### SaveDialogOptions + +```go +type SaveDialogOptions struct { + DefaultDirectory string + DefaultFilename string + Title string + Filters []FileFilter + ShowHiddenFiles bool + CanCreateDirectories bool + TreatPackagesAsDirectories bool +} +``` + +| Champ | Description | Win | Mac | Lin | +| -------------------------- | -------------------------------------------------------------- | --- | --- | --- | +| DefaultDirectory | Le répertoire que la boîte de dialogue affichera à l'ouverture | ✅ | ✅ | ✅ | +| DefaultFilename | Le nom du fichier par défaut | ✅ | ✅ | ✅ | +| Title | Titre pour la boite de dialogue | ✅ | ✅ | ✅ | +| [Filters](#filefilter) | Une liste de filtres de fichiers | ✅ | ✅ | ✅ | +| ShowHiddenFiles | Afficher les fichiers cachés par le système | | ✅ | ✅ | +| CanCreateDirectories | Autoriser l'utilisateur de créer des dossiers | | ✅ | | +| TreatPackagesAsDirectories | Autoriser la navigation dans les dossiers | | ✅ | | + +### MessageDialogOptions + +```go +type MessageDialogOptions struct { + Type DialogType + Title string + Message string + Buttons []string + DefaultButton string + CancelButton string +} +``` + +| Champ | Description | Win | Mac | Lin | +| ------------- | ---------------------------------------------------------------------------------------------- | -------------- | --- | --- | +| Type | Le type de boîte de dialogue de message: question, info... | ✅ | ✅ | ✅ | +| Title | Titre pour la boite de dialogue | ✅ | ✅ | ✅ | +| Message | Le message à afficher à l'utilisateur | ✅ | ✅ | ✅ | +| Buttons | La liste des noms des boutons | | ✅ | | +| DefaultButton | Le bouton avec ce texte doit être traité comme le bouton par défaut. Lié à la touche `entrée`. | ✅[*](#windows) | ✅ | | +| CancelButton | Le bouton avec ce texte doit être traité permettant d'annuler. Lié à la touche `echap` | | ✅ | | + +#### Windows + +Windows a des boites de dialogue standard dans lesquels les boutons ne sont pas personnalisables. La valeur retournée sera une des valeurs suivantes : "Ok", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No", "Try Again" ou "Continue". + +Pour les boites de dialogues pour les questions, le bouton par défaut est "Oui" et le bouton d'annulation est "Non". Cela peut être modifié en définissant la valeur `DefaultButton` à `"No"`. + +Exemple: +```go + result, err := runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Question", + Message: "Do you want to continue?", + DefaultButton: "No", + }) +``` + +#### Linux + +Linux a des boites de dialogue standard dans lesquels les boutons ne sont pas personnalisables. La valeur retournée sera de :"Ok", "Cancel", "Yes", "No" + +#### Mac + +Une boîte de dialogue sur Mac peut avoir jusqu'à 4 boutons. Si aucun `DefaultButton` ou `CancelButton` n'est donné, le premier bouton est considéré comme par défaut et est lié à la touche `entrée`. + +Pour le code suivant : + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "C'est ton tour", + Message: "Choisi un nombre", + Buttons: []string{"un", "deux", "trois", "quatre"}, +}) +``` + +le premier bouton est affiché comme étant celui par défaut : + +```mdx-code-block +
+ +
+
+``` + +Et si nous spécifions que le `DefaultButton` est "deux": + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, + DefaultButton: "two", +}) +``` + +le deuxième bouton est affiché comme étant la réponse par défaut. Lorsque la touche `entrée` est appuyée, la valeur "deux" est retournée. + +```mdx-code-block +
+ +
+
+``` + +Si nous spécifions maintenant `CancelButton` à "trois": + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, + DefaultButton: "two", + CancelButton: "three", +}) +``` + +le bouton avec "trois" est affiché en bas de la boîte de dialogue. Si la touche `echap` est appuyée, la valeur "trois" est retournée: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### DialogType + +```go +const ( + InfoDialog DialogType = "info" + WarningDialog DialogType = "warning" + ErrorDialog DialogType = "error" + QuestionDialog DialogType = "question" + ) +``` + +### FileFilter + +```go +type FileFilter struct { + DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)" + Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png" +} +``` + +#### Windows + +Windows vous permet d'utiliser plusieurs filtres de fichiers dans les boîtes de dialogue. Chaque FileFilter s'affichera comme une entrée séparée dans la boîte de dialogue : + +```mdx-code-block +
+ +
+
+
+
+``` + +#### Linux + +Linux vous permet d'utiliser plusieurs filtres de fichiers dans les boîtes de dialogue. Chaque FileFilter s'affichera comme une entrée séparée dans la boîte de dialogue : + +```mdx-code-block +
+ +
+
+
+
+``` + +#### Mac + +Les dialogues Mac n'ont qu'un ensemble unique de motifs pour filtrer les fichiers. Si plusieurs filtres de fichiers sont fournis, Wails utilisera tous les modèles définis. + +Exemple: + +```go + selection, err := runtime.OpenFileDialog(b.ctx, runtime.OpenDialogOptions{ + Title: "Select File", + Filters: []runtime.FileFilter{ + { + DisplayName: "Images (*.png;*.jpg)", + Pattern: "*.png;*.jpg", + }, { + DisplayName: "Videos (*.mov;*.mp4)", + Pattern: "*.mov;*.mp4", + }, + }, + }) +``` + +Cela se traduira par l'ouverture de la boîte de dialogue "Ouvrir un fichier" en utilisant `*.png,*.jpg,*.mov,*.mp4` comme filtres. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx new file mode 100644 index 00000000000..43d72885ea7 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx @@ -0,0 +1,37 @@ +--- +sidebar_position: 2 +--- + +# Événements + +Le runtime Wails fournit un système d'événements unifiés, où les événements peuvent être émis ou reçus par Go ou JavaScript. En option, des données peuvent être transmises avec les événements. Les écouteurs vont recevoir les données dans les types de donnée du langage correspondant. + +### EventsOn + +Cette méthode définit un listener pour le nom d'événement donné. Lorsqu'un événement de type `eventName` est [émis](#EventsEmit), la méthode définie en callback est déclenchée. Toutes les données supplémentaires envoyées avec l'événement émis seront passées en paramètre à la méthode définie en callback. Il renvoie une fonction pour annuler l'écouteur. + +Go: `EventsOn(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`
JS: `EventsOn(eventName string, callback function(optionalData?: any)): () => void` + +### EventsOff + +Cette méthode désactive l'évènement correspondant au nom donné, éventuellement plusieurs évènements peuvent être désinscrits via `additionalEventNames`. + +Go: `EventsOff(ctx context.Context, eventName string, additionalEventNames ...string)`
JS: `EventsOff(eventName string, ...additionalEventNames)` + +### EventsOnce + +Cette méthode définit un évènement pour le nom donné, mais ne se déclenchera qu'une seule fois. Il renvoie une fonction pour annuler l'évènement. + +Go: `EventsOnce(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`
JS: `EventsOnce(eventName string, callback function(optionalData?: any)): () => void` + +### EventsOnMultiple + +Cette méthode définit un évènement pour le nom donné, mais ne se déclenchera au maximum qu'un certain nombre de fois, définit avec le paramètre `counter`. Il renvoie une fonction pour annuler l'écouteur. + +Go: `EventsOnMultiple(ctx context.Context, eventName string, callback func(optionalData ...interface{}), counter int) func()`
JS: `EventsOnMultiple(eventName string, callback function(optionalData?: any), counter int): () => void` + +### EventsEmit + +Cette méthode émet l'événement donné. En option, des données peuvent être transmises avec l'événement. Cela déclenchera tous les événements. + +Go: `EventsEmit(ctx context.Context, eventName string, optionalData ...interface{})`
JS: `EventsEmit(eventName: string, ...optionalData: any)` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx new file mode 100644 index 00000000000..915ebc4ec9c --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx @@ -0,0 +1,85 @@ +--- +sidebar_position: 1 +--- + +# Introduction + +Le runtime est une bibliothèque qui fournit des méthodes utilitaires pour votre application. Il y a à la fois un runtime Go et JavaScript et le but est d'essayer de les maintenir à parité dans la mesure du possible. + +Il a des méthodes utilitaires pour : + +- [Fenêtre](window.mdx) +- [Menu](menu.mdx) +- [Boîte de dialogue](dialog.mdx) +- [Événements](events.mdx) +- [Navigateur](browser.mdx) +- [Log](log.mdx) +- [Clipboard](clipboard.mdx) + +Le Go Runtime est disponible en important `github.com/wailsapp/wails/v2/pkg/runtime`. Toutes les méthodes de ce paquet prennent un contexte comme premier paramètre. Ce contexte doit être obtenu à partir des méthodes [OnStartup](../options.mdx#onstartup) ou [OnDomReady](../options.mdx#ondomready). + +:::info Note + +Alors que le contexte sera fourni à la méthode [OnStartup](../options.mdx#onstartup) , il n'y a aucune garantie que l'exécution fonctionnera dans cette méthode car la fenêtre s'initialise dans un autre thread. Si vous souhaitez appeler des méthodes d'exécution au démarrage, utilisez [OnDomReady](../options.mdx#ondomready). + +::: + +La bibliothèque JavaScript est disponible sur le frontend via la carte `window.runtime`. Il y a un package d'exécution généré lors de l'utilisation du mode `dev` qui fournit des déclarations TypeScript pour l'exécution. Ceci devrait être situé dans le répertoire `wailsjs` dans votre répertoire frontend. + +### Cacher + +Go: `Hide(ctx context.Context)`
JS: `Hide()` + +Cache l'application. + +:::info Note + +Sur Mac, cela masquera l'application de la même manière que le bouton `Masquer` du menu des applications Mac standard. C'est une manière différente de cacher l'application, mais elle sera toujours au premier plan. Pour Windows et Linux, c'est actuellement la même chose que `WindowHide`. + +::: + +### Afficher + +Affiche l'application. + +:::info Note + +Sur Mac, cela va ramener l'application au premier plan. Pour Windows et Linux, c'est actuellement la même chose que `WindowShow`. + +::: + +Go: `Show(ctx context.Context)`
JS: `Show()` + +### Quitter + +Quitte l'application. + +Go: `Quit(ctx context.Context)`
JS: `Quit()` + +### Environnement + +Renvoie les détails de l'environnement actuel. + +Go: `Environment(ctx context.Context) EnvironmentInfo`
JS: `Environment(): Promise` + +#### EnvironmentInfo + +Go: + +```go +type EnvironmentInfo struct { + BuildType string + Platform string + Arch string +} +``` + +JS: + +```ts +interface EnvironmentInfo { + buildType: string; + platform: string; + arch: string; +} +``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx new file mode 100644 index 00000000000..45b7a07ed27 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 3 +--- + +# Log + +Le runtime Wails fournit un mécanisme de journalisation qui peut être appelé depuis Go ou JavaScript. Comme la plupart des loggers, il y a un certain nombre de niveaux de log : + +- Trace +- Debug +- Info +- Warning +- Error +- Fatal + +Le logger affichera tous les messages de log au niveau actuel ou supérieur. Exemple : Le niveau `Debug` affichera tous les messages sauf ceux du niveau `Trace`. + +### LogPrint + +Ajoute le message donné dans les logs en tant que message brut. + +Go: `LogPrint(ctx context.Context, message string)`
JS: `LogPrint(message: string)` + +### LogPrintf + +Ajoute le message donné dans les logs en tant que message brut. + +Go: `LogPrintf(ctx context.Context, format string, args ...interface{})`
+ +### LogTrace + +Ajoute le message donné dans les logs avec le niveau de log `Trace`. + +Go: `LogTrace(ctx context.Context, message string)`
JS: `LogTrace(message: string)` + +### LogTracef + +Ajoute le message donné dans les logs avec le niveau de log `Trace`. + +Go: `LogTracef(ctx context.Context, format string, args ...interface{})`
+ +### LogDebug + +Ajoute le message donné dans les logs avec le niveau de log `Debug`. + +Go: `LogDebug(ctx context.Context, message string)`
JS: `LogDebug(message: string)` + +### LogDebugf + +Ajoute le message donné dans les logs avec le niveau de log `Debug`. + +Go: `LogDebugf(ctx context.Context, format string, args ...interface{})`
+ +### LogInfo + +Ajoute le message donné dans les logs avec le niveau de log `Info`. + +Go: `LogInfo(ctx context.Context, message string)`
JS: `LogInfo(message: string)` + +### LogInfof + +Ajoute le message donné dans les logs avec le niveau de log `Info`. + +Go: `LogInfof(ctx context.Context, format string, args ...interface{})`
+ +### LogWarning + +Ajoute le message donné dans les logs avec le niveau de log `Warning`. + +Go: `LogWarning(ctx context.Context, message string)`
JS: `LogWarning(message: string)` + +### LogWarningf + +Ajoute le message donné dans les logs avec le niveau de log `Warning`. + +Go: `LogWarningf(ctx context.Context, format string, args ...interface{})`
+ +### LogError + +Ajoute le message donné dans les logs avec le niveau de log `Error`. + +Go: `LogError(ctx context.Context, message string)`
JS: `LogError(message: string)` + +### LogErrorf + +Ajoute le message donné dans les logs avec le niveau de log `Error`. + +Go: `LogErrorf(ctx context.Context, format string, args ...interface{})`
+ +### LogFatal + +Ajoute le message donné dans les logs avec le niveau de log `Fatal`. + +Go: `LogFatal(ctx context.Context, message string)`
JS: `LogFatal(message: string)` + +### LogFatalf + +Ajoute le message donné dans les logs avec le niveau de log `Fatal`. + +Go: `LogFatalf(ctx context.Context, format string, args ...interface{})`
+ +### LogSetLogLevel + +Définit le niveau des logs. En JavaScript, le nombre se rapporte aux niveaux de log suivants : + +| Valeur | Niveau de log | +| ------ | ------------- | +| 1 | Trace | +| 2 | Debug | +| 3 | Info | +| 4 | Warning | +| 5 | Error | + +Go: `LogSetLogLevel(ctx context.Context, level logger.LogLevel)`
JS: `LogSetLogLevel(level: number)` + +## Utiliser un Logger Personnalisé + +Un logger personnalisé peut être utilisé en le définissant dans l'option de l'application [Logger](../options.mdx#logger) . La seule condition est que le logger implémente l'interface `logger.Logger` définie dans `github.com/wailsapp/wails/v2/pkg/logger`: + +```go title="logger.go" +type Logger interface { + Print(message string) + Trace(message string) + Debug(message string) + Info(message string) + Warning(message string) + Error(message string) + Fatal(message string) +} +``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx new file mode 100644 index 00000000000..cd78d31aa31 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx @@ -0,0 +1,25 @@ +--- +sidebar_position: 6 +--- + +# Menu + +Ces méthodes sont liées au menu de l'application. + +:::info JavaScript + +Le menu n'est actuellement pas pris en charge lors de l'exécution de JS. + +::: + +### MenuSetApplicationMenu + +Définit le menu de l'application dans le [menu](../menus.mdx) donné. + +Go: `MenuSetApplicationMenu(ctx context.Context, menu *menu.Menu)` + +### MenuUpdateApplicationMenu + +Met à jour le menu de l'application, avec toutes les autres modifications déjà appliquées via `MenuSetApplicationMenu`. + +Go: `MenuUpdateApplicationMenu(ctx context.Context)` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx new file mode 100644 index 00000000000..457c92ebff9 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx @@ -0,0 +1,38 @@ +--- +sidebar_position: 9 +--- + +# Screen + +These methods provide information about the currently connected screens. + +### ScreenGetAll + +Returns a list of currently connected screens. + +Go: `ScreenGetAll(ctx context.Context) []screen`
+JS: `ScreenGetAll()` + +#### Screen + +Go struct: + +```go +type Screen struct { + IsCurrent bool + IsPrimary bool + Width int + Height int +} +``` + +Typescript interface: + +```ts +interface Screen { + isCurrent: boolean; + isPrimary: boolean; + width : number + height : number +} +``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx new file mode 100644 index 00000000000..e9d915a4f9b --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx @@ -0,0 +1,227 @@ +--- +sidebar_position: 4 +--- + +# Fenêtre + +Ces méthodes donnent le contrôle de la fenêtre de l'application. + +### WindowSetTitle + +Définit le texte dans la barre de titre de la fenêtre. + +Go: `WindowSetTitle(ctx context.Context, title string)`
JS: `WindowSetTitle(title: string)` + +### WindowFullscreen + +Mets la fenêtre en plein écran. + +Go: `WindowFullscreen(ctx context.Context)`
JS: `WindowFullscreen()` + +### WindowUnfullscreen + +Restaure les dimensions et la position de la fenêtre avant le plein écran. + +Go: `WindowUnfullscreen(ctx context.Context)`
JS: `WindowUnfullscreen()` + +### WindowIsFullscreen + +Renvoie vrai si la fenêtre est en plein écran. + +Go: `WindowIsFullscreen(ctx context.Context) bool`
JS: `WindowIsFullscreen() bool` + +### WindowCenter + +Centre la fenêtre sur le moniteur sur laquelle la fenêtre est actuellement ouverte. + +Go: `WindowCenter(ctx context.Context)`
JS: `WindowCenter()` + +### WindowExecJS + +Exécute du code JS dans la fenêtre. + +Cette méthode exécute le code dans le navigateur de manière asynchrone et retourne immédiatement le résultat. Si le script cause des erreurs, elles ne seront disponibles que dans la console du navigateur. + +Go: `WindowExecJS(ctx context.Context, js string)` + +### WindowReload + +Effectue un "rechargement" (Recharge la page courante). + +Go: `WindowReload(ctx context.Context)`
JS: `WindowReload()` + +### WindowReloadApp + +Recharge le frontend de l'application. + +Go: `WindowReloadApp(ctx context.Context)`
JS: `WindowReloadApp()` + +### WindowSetSystemDefaultTheme + +Windows seulement. + +Go: `WindowSetSystemDefaultTheme(ctx context.Context)`
JS: `WindowSetSystemDefaultTheme()` + +Définit le thème de fenêtre à la valeur par défaut du système (sombre/clair). + +### WindowSetLightTheme + +Windows seulement. + +Go: `WindowSetLightTheme(ctx context.Context)`
JS: `WindowSetLightTheme()` + +Définit le thème clair à la fenêtre. + +### WindowSetDarkTheme + +Windows seulement. + +Go: `WindowSetDarkTheme(ctx context.Context)`
JS: `WindowSetDarkTheme()` + +Définit le thème sombre à la fenêtre. + +### WindowShow + +Affiche la fenêtre, si elle est actuellement masquée. + +Go: `WindowShow(ctx context.Context)`
JS: `WindowShow()` + +### WindowHide + +Masque la fenêtre, si elle est actuellement visible. + +Go: `WindowHide(ctx context.Context)`
JS: `WindowHide()` + +### WindowIsNormal + +Renvoie vrai si la fenêtre n'est pas minimisée, maximisée ou plein écran. + +Go: `WindowIsNormal(ctx context.Context) bool`
JS: `WindowIsNormal() bool` + +### WindowSetSize + +Définit la largeur et la hauteur de la fenêtre. + +Go: `WindowSetSize(ctx context.Context, width int, height int)`
JS: `WindowSetSize(width: number, height: number)` + +### WindowGetSize + +Retourne la largeur et la hauteur de la fenêtre. + +Go: `WindowGetSize(ctx context.Context) (width int, height int)`
JS: `WindowGetSize() : Size` + +### WindowSetMinSize + +Définit la taille minimale de la fenêtre. Redimensionnera la fenêtre si la fenêtre est actuellement plus petite que les dimensions données. + +Définir une taille de `0,0` désactivera cette contrainte. + +Go: `WindowSetMinSize(ctx context.Context, width int, height int)`
JS: `WindowSetMinSize(width: number, height: number)` + +### WindowSetMaxSize + +Définit la taille maximale de la fenêtre. Redimensionnera la fenêtre si la fenêtre est actuellement plus grande que les dimensions données. + +Définir une taille de `0,0` désactivera cette contrainte. + +Go: `WindowSetMaxSize(ctx context.Context, width int, height int)`
JS: `WindowSetMaxSize(width: number, height: number)` + +### WindowSetAlwaysOnTop + +Paramètre pour faire en sorte que la fenêtre soit toujours au dessus des autres ou non. + +Go: `WindowSetAlwaysOnTop(ctx context.Context, b bool)`
JS: `WindowSetAlwaysOnTop(b: Boolen)` + +### WindowSetPosition + +Définit la position de la fenêtre par rapport au moniteur sur lequel la fenêtre est activée. + +Go: `WindowSetPosition(ctx context.Context, x int, y int)`
JS: `WindowSetPosition(x: number, y: number)` + +### WindowGetPosition + +Récupère la position de la fenêtre relative au moniteur sur lequel la fenêtre est activée. + +Go: `WindowGetPosition(ctx context.Context) (x int, y int)`
JS: `WindowGetPosition() : Position` + +### WindowMaximiseWindowMaximise + +Maximise la fenêtre pour remplir l'écran. + +Go: `WindowMaximise(ctx context.Context)`
JS: `WindowMaximise()` + +### WindowUnmaximise + +Restaure la fenêtre aux dimensions et à la position avant qu'elle soit maximisée. + +Go: `WindowUnmaximise(ctx context.Context)`
JS: `WindowUnmaximise()` + +### WindowIsMaximised + +Renvoie vrai si la fenêtre est maximisée. + +Go: `WindowIsMaximised(ctx context.Context) bool`
JS: `WindowIsMaximised() bool` + +### WindowToggleMaximise + +Option permettant de basculer entre la maximisation de la fenêtre et sa non maximisation. + +Go: `WindowToggleMaximise(ctx context.Context)`
JS: `WindowToggleMaximise()` + +### WindowMinimise + +Minimise la fenêtre. + +Go: `WindowMinimise(ctx context.Context)`
JS: `WindowMinimise()` + +### WindowUnminimise + +Restaure la fenêtre aux dimensions et à la position avant qu'elle soit minimisée. + +Go: `WindowUnminimise(ctx context.Context)`
JS: `WindowUnminimise()` + +### WindowIsMinimised + +Renvoie vrai si la fenêtre est minimisée. + +Go: `WindowIsMinimised(ctx context.Context) bool`
JS: `WindowIsMinimised() bool` + +### WindowSetBackgroundColour + +Définit la couleur de fond de la fenêtre avec la couleur RGBA donnée. Cette couleur sera visible au travers de tous les pixels transparents. + +Les valeurs valides pour R, G, B et A sont entre 0 et 255 inclus. + +:::info Windows + +Sous Windows, seules les valeurs 0 et 255 sont prises en charge pour A. Toute valeur qui n'est pas 0 sera considérée comme 255. + +::: + +Go: `WindowSetBackgroundColour(ctx context.Context, R, G, B, A uint8)`
JS: `WindowSetBackgroundColour(R, G, B, A)` + +### WindowPrint + +Opens tha native print dialog. + +Go: `WindowPrint(ctx context.Context)`
JS: `WindowPrint()` + +## Définitions d'objets TypeScript + +### Position + +```ts +interface Position { + x: number; + y: number; +} +``` + +### Size (taille) + +```ts +interface Size { + w: number; + h: number; +} +``` diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx new file mode 100644 index 00000000000..cb2b780b665 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx @@ -0,0 +1,245 @@ +--- +sidebar_position: 20 +--- + +# API Chiens + +```mdx-code-block +
+ +
+
+``` + +:::note + +Ce tutoriel a été gracieusement fourni par [@tatadan](https://twitter.com/tatadan) et fait partie de leur [dépôt d'exemples Wails](https://github.com/tataDan/wails-v2-examples). + +::: + +Dans ce tutoriel, nous allons développer une application qui récupère des photos de chiens du web et les affiche. + +### Créer le projet + +Créons l'application. Depuis un terminal saisissez : `wails init -n dogs-api -t svelte` + +Note: Nous pouvons ajouter l'une des options suivantes `-ide vscode` ou `-ide goland` à la fin de la commande si vous voulez ajouter le support d'un IDE. + +Maintenant, exécutons `cd dogs-api` et commençons à éditer les fichiers du projet. + +### Retirer le code inutilisé + +Nous allons commencer par supprimer certains éléments que nous savons que nous n'utiliserons pas : + +- Ouvrez `app.go` et supprimez les lignes suivantes : + +```go +// Greet returns a greeting for the given name +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s, It's show time!", name) +} +``` + +- Ouvrez `frontend/src/App.svelte` et supprimez toutes les lignes. +- Supprimer le fichier `frontend/src/assets/images/logo-universal.png` + +### Créer notre application + +Ajoutons maintenant notre nouveau code Go. + +Ajoutez les déclarations struct suivantes dans `app.go` avant la déclaration des fonctions: + +```go +type RandomImage struct { + Message string + Status string +} + +type AllBreeds struct { + Message map[string]map[string][]string + Status string +} + +type ImagesByBreed struct { + Message []string + Status string +} +``` + +Ajouter les fonctions suivantes dans `app.go` (après la déclaration de la fonction déjà existante): + +```go +func (a *App) GetRandomImageUrl() string { + response, err := http.Get("https://dog.ceo/api/breeds/image/random") + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data RandomImage + json.Unmarshal(responseData, &data) + + return data.Message +} + +func (a *App) GetBreedList() []string { + var breeds []string + + response, err := http.Get("https://dog.ceo/api/breeds/list/all") + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data AllBreeds + json.Unmarshal(responseData, &data) + + for k := range data.Message { + breeds = append(breeds, k) + } + + sort.Strings(breeds) + + return breeds +} + +func (a *App) GetImageUrlsByBreed(breed string) []string { + + url := fmt.Sprintf("%s%s%s%s", "https://dog.ceo/api/", "breed/", breed, "/images") + response, err := http.Get(url) + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data ImagesByBreed + json.Unmarshal(responseData, &data) + + return data.Message +} +``` + +Modifiez la section `import` de `app.go` pour ressembler à ceci : + +```go +import ( + "context" + "fmt" + "encoding/json" + "io/ioutil" + "log" + "net/http" + "sort" +) +``` + +Ajouter les lignes suivantes dans `frontend/src/App.svelte`: + + +```html + + +

Dogs API

+
+ + Click on down arrow to select a breed + + +
+
+{#if showRandomPhoto} + No dog found +{/if} +{#if showBreedPhotos} + {#each photos as photo} + No dog found + {/each} +{/if} + + +``` + + +### Tester l'application + +Pour générer les liaisons et tester l'application, exécutez `wails dev`. + +### Compiler l'application + +Pour compiler l'application en un seul binaire, exécutez `wails build`. diff --git a/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx new file mode 100644 index 00000000000..2beff220ec5 --- /dev/null +++ b/website/i18n/fr/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx @@ -0,0 +1,123 @@ +--- +sidebar_position: 10 +--- + +# Hello World + +Le but de ce tutoriel est de vous faire créer l'application la plus basique en utilisant Wails. Vous serez capables de : + +- Créer une nouvelle application Wails +- Compiler l'application +- Démarrer l'application + +:::note + +Ce tutoriel utilise Windows comme plate-forme cible. La sortie variera légèrement selon votre système d'exploitation. + +::: + +## Créer une nouvelle application Wails + +Pour créer une nouvelle application Wails utilisant le template Vanilla JS par défaut, vous devez exécuter la commande suivante : + +```bash +wails init -n helloworld +``` + +Vous devriez voir quelque chose de similaire à ce qui suit : + +``` +Wails CLI v2.0.0 + +Initialising Project 'helloworld' +--------------------------------- + +Project Name: helloworld +Project Directory: C:\Users\leaan\tutorial\helloworld +Project Template: vanilla +Template Support: https://wails.io + +Initialised project 'helloworld' in 232ms. +``` + +Cela va créer un nouveau dossier nommé `helloworld` dans le dossier actuel. Dans ce dossier, vous trouverez un certain nombre de fichiers : + +``` +build/ - Contains the build files + compiled application +frontend/ - Contains the frontend files +app.go - Contains the application code +main.go - The main program with the application configuration +wails.json - The project configuration file +go.mod - The go module file +go.sum - The go module checksum file +``` + +## Compiler l'application + +Pour compiler l'application, déplacez-vous dans le dossier du nouveau projet `helloworld` et exécutez la commande suivante : + +```bash +wails build +``` + +Vous devriez voir quelque chose comme ça : + +``` +Wails CLI v2.0.0 + +App Type: desktop +Platforms: windows/amd64 +Compiler: C:\Users\leaan\go\go1.18.3\bin\go.exe +Build Mode: Production +Devtools: false +Skip Frontend: false +Compress: false +Package: true +Clean Build Dir: false +LDFlags: "" +Tags: [] +Race Detector: false + +Building target: windows/amd64 +------------------------------ + - Installing frontend dependencies: Done. + - Compiling frontend: Done. + - Generating bundle assets: Done. + - Compiling application: Done. +Built 'C:\Users\leaan\tutorial\helloworld\build\bin\helloworld.exe' in 10.616s. +``` + +Cela a compilé l'application et l'a enregistré dans le dossier `build/bin`. + +## Démarrer l'application + +Si on voit le dossier `build/bin` dans l'explorateur Windows, nous devrions voir le binaire de notre projet : + +```mdx-code-block +
+ +
+
+``` + +On peut l'exécuter en simplement double-cliquant sur le fichier `helloworld.exe`. + +Sur Max, Wails va générer un fichier `helloworld.app` qui peut être exécuté en simplement double-cliquant dessus. + +Sur Linux, vous pouvez exécuter l'application en utilisant `./helloworld` depuis le répertoire `build/bin`. + +Vous devriez voir l'application fonctionner comme prévu : + +```mdx-code-block +
+ +
+
+``` diff --git a/website/versioned_docs/version-v2.6.0/appendix/_category_.json b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/appendix/_category_.json similarity index 100% rename from website/versioned_docs/version-v2.6.0/appendix/_category_.json rename to website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/appendix/_category_.json diff --git a/website/versioned_docs/version-v2.6.0/community/_category_.json b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/_category_.json similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/_category_.json rename to website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/_category_.json diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx new file mode 100644 index 00000000000..b7b80b83939 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 2 +--- + +# リンク + +このページは、コミュニティ関連のリンクの一覧です。 リンクを追加したい場合は、プルリクエストを送信(ページ下部の`このページを編集`をクリック) してください。 + +## Awesome Wails + +Wailsに関する[最高のリンク一覧](https://github.com/wailsapp/awesome-wails)です。 + +## サポートチャネル + +- [Wails Discordサーバ](https://discord.gg/JDdSxwjhGf) +- [Github Issues](https://github.com/wailsapp/wails/issues) +- [v2ベータディスカッションボード](https://github.com/wailsapp/wails/discussions/828) + +## ソーシャルメディア + +- [Twitter](https://twitter.com/wailsapp) +- [Wails中国語コミュニティQQグループ](https://qm.qq.com/cgi-bin/qm/qr?k=PmIURne5hFGNd7QWzW5qd6FV-INEjNJv&jump_from=webapi) - グループナンバー: 1067173054 + +## その他のチュートリアルや記事 + +- [掲示板を作ってみる](https://blog.customct.com/building-bulletin-board) diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/_category_.json b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/_category_.json similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/_category_.json rename to website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/_category_.json diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx new file mode 100644 index 00000000000..7cf3d52b5a6 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx @@ -0,0 +1,10 @@ +# BulletinBoard + +```mdx-code-block +

+ +
+

+``` + +[BulletinBoard](https://github.com/raguay/BulletinBoard)は、静的なメッセージや、スクリプト用にユーザから情報を得るためのダイアログを表示する、汎用的なメッセージボードアプリケーションです。 後者はユーザから情報を取得するために使用でき、新しいダイアログを作成するためのTUIを備えています。 システム上で動作し続け、必要に応じて情報を表示・非表示できるように設計されています。 システム上のファイルを監視し、内容が変更されたときにBulletinBoardに送信するという処理もできます。 これは、私のワークフローと相性が良いのです。 なお、プログラムに情報を送信するための[Alfredワークフロー](https://github.com/raguay/MyAlfred/blob/master/Alfred%205/EmailIt.alfredworkflow)があります。 また、[EmailIt](https://github.com/raguay/EmailIt)と連携するためのワークフローもあります。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..e451971b98c --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx @@ -0,0 +1,39 @@ +# CFN トラッカー + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - ストリートファイ +ター 6 または V CFN プロフィールのライブマッチを追跡します。 開始するには +、[Web サイト](https://cfn.williamsjokvist.se/) を確認してください。 + +## 特徴 + +- リアルタイムの試合追跡 +- 試合ログと統計の保存 +- ブラウザソース経由で OBS にライブ統計を表示するためのサポート +- SF6 と SFV の両方をサポート +- ユーザーが CSS を使用して独自の OBS ブラウザ テーマを作成できる機能 + +### Wails とともに使用される主要なテクノロジー + +- [タスク](https://github.com/go-task/task) - Wails CLI をラップして一般的なコマ + ンドを使いやすくする +- [React](https://github.com/facebook/react) - 豊富なエコシステム (基数、フレー + マーモーション) で選ばれました +- [Bun](https://github.com/oven-sh/bun) - 依存関係の高速解決とビルド時間に使用さ + れます。 +- [Rod](https://github.com/go-rod/rod) - 認証とポーリングの変更のためのヘッドレ + スブラウザ自動化 +- [SQLite](https://github.com/mattn/go-sqlite3) - 一致、セッション、プロファイル + の保存に使用されます +- [サーバー送信イベント](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + 追跡更新を OBS ブラウザ ソースに送信するための http ストリーム +- [i18next](https://github.com/i18next/) - Go レイヤーからローカリゼーション オ + ブジェクトを提供するバックエンド コネクタを使用 +- [xstate](https://github.com/statelyai/xstate) - 認証プロセスと追跡のためのステ + ート マシン diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx new file mode 100644 index 00000000000..970e632a2d7 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx @@ -0,0 +1,10 @@ +# EmailIt + +```mdx-code-block +

+ +
+

+``` + +[EmailIt](https://github.com/raguay/EmailIt/)はWails 2で作成されており、9個のノートパット、テキスト操作のためのスクリプト、およびテンプレートを備えた、マークダウンベースのEメール送信ソフトです。 また、システム内のファイルに対してEmailItのスクリプトを実行するためのスクリプトターミナルを備えています。 スクリプトとテンプレートは、コマンドライン自体から、またはAlfred、Keyboard Maestro、Dropzone、PopClipの拡張機能から使用することができます。 さらに、GitHubからダウンロードしたスクリプトやテーマにも対応しています。 ドキュメントは未完成ですが、ブログラム自体は動作します。 Wails 2とSvelteを使用して構築されており、ユニバーサルmacOSアプリケーションとしてダウンロードできます。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx new file mode 100644 index 00000000000..b6395c7abd0 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx @@ -0,0 +1,12 @@ +# EncryptEasy + +```mdx-code-block +

+ +
+

+``` + +**[EncryptEasy](https://www.encrypteasy.app)は、シンプルで使いやすいPGP暗号化ツールで、すべての連絡先の鍵を管理することができます。 暗号化は簡単にできるべきです。 Wailsで開発されました。** + +PGPを使用したメッセージの暗号化は、業界の標準です。 誰もが、秘密鍵と公開鍵を所持しています。 あなたの秘密鍵は、あなただけがメッセージを読めるように、常に秘密にしておく必要があります。 あなたの公開鍵は、暗号化されたメッセージを送信したい人に配布します。 鍵の管理、メッセージの暗号化、およびメッセージの復号化は、スムーズにできなければなりません。 EncryptEasyはそれらを簡単に実現します。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx new file mode 100644 index 00000000000..4e4295b26ab --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx @@ -0,0 +1,13 @@ +# ESP Studio + +```mdx-code-block +

+ +
+

+``` + +[ESP Studio](https://github.com/torabian/esp-studio) - クロスプラットフォーム、デスクトップ、クラウド、組み込みソフトウェア +ESP/Arduino デバイスの制御、複雑な IOT ワークフローと制御システムの構築用 \ No newline at end of file diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx new file mode 100644 index 00000000000..a9d9ad651ef --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx @@ -0,0 +1,16 @@ +# FileHound Export Utility + +```mdx-code-block +

+ +
+

+``` + +[FileHound Export Utility](https://www.filehound.co.uk/) FileHoundは、安全なファイル保管、ビジネスプロセスの自動化、およびSmartCapture機能のための、クラウドドキュメント管理プラットフォームです。 + +FileHound Export Utilityを使用すると、FileHoundの管理者はバックアップやリカバリのために、安全なドキュメントとデータ抽出タスクを実行できます。 このアプリケーションは、選択したフィルタにもとづいて、FileHoundに保存されているすべての文書やメタデータをダウンロードします。 メタデータはJSON形式とXML形式の両方でエクスポートされます。 + +バックエンド: Go 1.15 Wails 1.11.0 go-sqlite3 1.14.6 go-linq 3.2 + +フロントエンド: Vue 2.6.11 Vuex 3.4.0 TypeScript Tailwind 1.9.6 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx new file mode 100644 index 00000000000..611c60d5fac --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx @@ -0,0 +1,10 @@ +# hiposter + +```mdx-code-block +

+ +
+

+``` + +[hiposter](https://github.com/obity/hiposter)は、シンプルで効率的に使用できる、http APIテストクライアントツールです。 Wails、Go、sveltejsで構築されました。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx new file mode 100644 index 00000000000..668173ebe9e --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx @@ -0,0 +1,14 @@ +# Minecraft Updater + +```mdx-code-block +

+ +
+

+``` + +[Minecraft Updater](https://github.com/Gurkengewuerz/MinecraftModUpdater)は、ユーザベースMinecraft Modを更新および同期するためのユーティリティツールです。 Wails2とReactで構築されており、フロントエンドフレームワークには[antd](https://ant.design/)を使用しています。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx new file mode 100644 index 00000000000..a8020f6be3a --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx @@ -0,0 +1,14 @@ +# Modal File Manager + +```mdx-code-block +

+ +
+

+``` + +[Modal File Manager](https://github.com/raguay/ModalFileManager)は、Web技術を使用した、デュアルペインファイルマネージャです。 [こちら](https://github.com/raguay/ModalFileManager-NWjs)でもともと公開していたNW.jsで構築されたものをベースとしています。 本バージョンでは、フロントエンドのコードには前と同様にSvelteを使用(NW.jsを使用していた時から大幅な修正はありました)しましたが、バックエンドの実装にはWails 2を使用しました。 この実装によって、コマンドラインの`rm`、`cp`などのコマンドを使用しなくなりましたが、テーマや拡張機能のダウンロードのために、システム上でgitのインストールは必要となります。 Goで完全にコード化されており、以前のバージョンよりもはるかに高速に実行されます。 + +このファイルマネージャは、Vimと同じ、状態制御キーボード操作の原理に基づいて設計されています。 状態の数に制限はなく、とてもプログラマブルです。 つまり、無数にキーボード構成を作成・使用することができます。 この点は、他のファイルマネージャとの主な違いと言えるでしょう。 また、GitHubからテーマや拡張機能をダウンロードできます。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx new file mode 100644 index 00000000000..00159268f08 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx @@ -0,0 +1,10 @@ +# Molley Wallet + +```mdx-code-block +

+ +
+

+``` + +[Molly Wallet](https://github.com/grvlle/constellation_wallet/)は、Constellation Networkの公式$DAGウォレットです。 ユーザは、$DAGトランザクションの生成に限らず、様々な方法でHypergraph Networkとやり取りすることができます。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx new file mode 100644 index 00000000000..7b5f59d15fb --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx @@ -0,0 +1,14 @@ +# October + +```mdx-code-block +

+ +
+

+``` + +[October](https://october.utf9k.net)は、[Kobo eReaders](https://en.wikipedia.org/wiki/Kobo_eReader)からハイライトを抽出し、簡単に[Readwise](https://readwise.io)へ転送できる、シンプルなWailsアプリケーションです。 + +[UPX圧縮](https://upx.github.io/)なしで、すべてのプラットフォームで10MB以下という、比較的小さなサイズとなっています! + +これとは対照的に、開発者が以前にElectronで作成したものは、簡単に数百MBにまで膨らんでしまいました。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx new file mode 100644 index 00000000000..b02394d2779 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx @@ -0,0 +1,10 @@ +# Optimus + +```mdx-code-block +

+ +
+

+``` + +[Optimus](https://github.com/splode/optimus)は、画像最適化のためのデスクトップアプリケーションです。 WebP、JPEG、PNG形式画像の相互変換や圧縮をサポートしています。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx new file mode 100644 index 00000000000..3066a9799e9 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx @@ -0,0 +1,10 @@ +# Portfall + +```mdx-code-block +

+ +
+

+``` + +[Portfall](https://github.com/rekon-oss/portfall) - すべてのクラスタUIに簡単にアクセスできる、デスクトップk8s port-forwardingポータルです。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx new file mode 100644 index 00000000000..348ffdd5290 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx @@ -0,0 +1,12 @@ +# Restic Browser + +```mdx-code-block +

+ +
+

+``` + +[Restic-Browser](https://github.com/emuell/restic-browser) - resticリポジトリを参照およびリストアするための、シンプルでクロスプラットフォームな[restic](https://github.com/restic/restic)バックアップGUIツールです。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx new file mode 100644 index 00000000000..b1e66ae7b8c --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx @@ -0,0 +1,21 @@ +# RiftShare + +```mdx-code-block +

+ +
+

+``` + +誰にとっても簡単、安全、そして無料のファイル共有。 詳しくは[Riftshare.app](https://riftshare.app)をご覧ください。 + +## 機能 + +- ローカルネットワーク内またはインターネット経由で、簡単にセキュアなコンピュータ間ファイル共有が可能 +- [magic wormhole プロトコル](https://magic-wormhole.readthedocs.io/en/latest/)を介したファイル・ディレクトリのセキュアな送信をサポート +- magic wormholeを使用する他のすべてのアプリ(magic-wormhole、wormhole-william CLI、wormhole-guiなど) との互換性 +- 選択された複数ファイルを自動圧縮して一括送信 +- フルアニメーション、プログレスバー、および送受信のキャンセルをサポート +- OSネイティブのファイル選択UIを利用可能 +- 受信したファイルをワンクリックで開ける +- 自動アップデート - 最新のリリースを気にする必要はありません! diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx new file mode 100644 index 00000000000..9ab6d88d51e --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx @@ -0,0 +1,10 @@ +# ScriptBar + +```mdx-code-block +

+ +
+

+``` + +[ScriptBar](https://GitHub.com/raguay/ScriptBarApp)は、スクリプトまたは[Node-Red](https://nodered.org)サーバの出力を表示するためのプログラムです。 EmailItプログラムで定義されたプログラムを実行し、出力を表示します。 xBarやTextBarのスクリプトも使用できますが、現時点ではTextBarのスクリプトが正常に動作します。 また、システム上にスクリプトの出力を表示できます。 ScriptBarはそれらの情報をメニューバーには表示させず、簡単に参照できる便利なウィンドウ上に表示されます。 複数のタブを使用して、様々な情報を表示できます。 よくアクセスするWebサイトへのリンクを配置することもできます。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx new file mode 100644 index 00000000000..bcca578edcc --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx @@ -0,0 +1,10 @@ +# Surge + +```mdx-code-block +

+ +
+

+``` + +[Surge](https://getsurge.io/)は、ブロックチェーン技術を使用して、100%匿名でのファイル転送ができるように設計された、p2pファイル共有アプリです。 エンドツーエンド暗号化に対応、分散型、そしてオープンソースである点が、Surgeの特徴です。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx new file mode 100644 index 00000000000..e3124bab727 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx @@ -0,0 +1,11 @@ +# Tiny RDM + +```mdx-code-block +

+ + +
+

+``` + +The [Tiny RDM](https://redis.tinycraft.cc/) application is an open-source, modern lightweight Redis GUI. It has a beautful UI, intuitive Redis database management, and compatible with Windows, Mac, and Linux. It provides visual key-value data operations, supports various data decoding and viewing options, built-in console for executing commands, slow log queries and more. diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx new file mode 100644 index 00000000000..d44b2280183 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx @@ -0,0 +1,10 @@ +# Wally + +```mdx-code-block +

+ +
+

+``` + +[Wally](https://ergodox-ez.com/pages/wally)は、[Ergodox](https://ergodox-ez.com/)キーボード公式の、ファームウェアフラッシャーです。 とても見栄えが良く、GoのパワーとWeb開発技術の豊富なグラフィカルツールを組み合わせるという、Wailsで達成できる機能を示す良い例となるアプリです。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx new file mode 100644 index 00000000000..6674a7d1652 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx @@ -0,0 +1,19 @@ +# Minecraft launcher for WarMine + +```mdx-code-block +

+ + +
+

+``` + +[Minecraft launcher for WarMine](https://warmine.ru/)は、Modを導入したゲームサーバに簡単にアクセスしたり、ゲームアカウントを管理できるWailsアプリケーションです。 + +ランチャーでは、ゲームファイルをダウンロードし、その整合性のチェックして、様々なカスタマイズが可能なバックエンドからの起動引数を使用してゲームを起動します。 + +フロントエンドはSvelteで記述され、ランチャー全体は9MBに収まり、Windows 7-11をサポートしています。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx new file mode 100644 index 00000000000..eedc72d97e8 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx @@ -0,0 +1,10 @@ +# Wombat + +```mdx-code-block +

+ +
+

+``` + +[Wombat](https://github.com/rogchap/wombat)はクロスプラットフォーム対応のgRPCクライアントです。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx new file mode 100644 index 00000000000..94e0e09f2ab --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx @@ -0,0 +1,10 @@ +# Ytd + +```mdx-code-block +

+ +
+

+``` + +[Ytd](https://github.com/marcio199226/ytd/tree/v2-wails)はYouTubeからトラックをダウンロードしたり、オフラインプレイリストを作成して友達と共有するためのアプリです。友達は、あなたのプレイリストを内蔵プレーヤーで再生したり、オフラインで聴くためにダウンロードしたりできます。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx new file mode 100644 index 00000000000..3dc92d2fbd9 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx @@ -0,0 +1,69 @@ +--- +sidebar_position: 1 +--- + +# テンプレート + +このページでは、コミュニティがサポートしているテンプレートを紹介しています。 このページに新たにテンプレートを含めたい場合は、このページの下側にある`このページを編集`をクリックして、プルリクエストを出してください。 独自テンプレートの作成方法については、[テンプレート](../guides/templates.mdx)ガイドをご覧ください。 + +これらのテンプレートを使用するには、`wails init -n "プロジェクト名" -t [テンプレートのリンク[@バージョン]]`コマンドを実行してください。 + +バージョンサフィックスが無い場合は、デフォルトで、メインブランチのコードテンプレートが使用されます。 バージョンサフィックスがある場合は、当該バージョンのタグに対応するコードテンプレートが使用されます。 + +例: `wails init -n "プロジェクト名" -t https://github.com/misitebao/wails-template-vue` + +:::warning 注意 + +**Wailsプロジェクトでは、サードパーティ製テンプレートのメンテナンスは行っておらず、責任も負いません!** + +テンプレートについてよく分からない場合は、`package.json`および`wails.json`を確認し、どのようなスクリプトが実行されるのかや、どのようなパッケージがインストールされるのかを調べてください。 + +::: + +## Vue + +- [wails-template-vue](https://github.com/misitebao/wails-template-vue) - VueのエコシステムをベースにしたWailsテンプレート (TypeScript、ダークテーマ、i18n、シングルページルーティング、TailwindCSSを統合) +- [wails-vite-vue-ts](https://github.com/codydbentley/wails-vite-vue-ts) - Viteを使用したVue 3 TypeScript (および機能を追加する手順) +- [wails-vite-vue-the-works](https://github.com/codydbentley/wails-vite-vue-the-works) - Vite、Vuex、Vue Router、SaaS、ESLint + Prettier を使用した Vue 3 TypeScript +- [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier) を使用したテンプレート +- [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier, <script setup>によるComposition API) を使用したテンプレート +- [wails-template-naive](https://github.com/tk103331/wails-template-naive) - Naive UI(Vue3のコンポーネントライブラリ)をベースにしたWailsテンプレート + +## Angular + +- [wails-template-angular](https://github.com/mateothegreat/wails-template-angular) - 15以上のAngularアクションを含み、すぐに実装に取り掛かれるテンプレート +- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - TypeScript、Sass、ホットリロード、コード分割、i18n を使用した Angular + +## React + +- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - reactjsを使用したテンプレート +- [wails-react-template](https://github.com/flin7/wails-react-template) - ライブ開発をサポートしたReactの最小テンプレート +- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - Next.js、TypeScript を使用したテンプレート +- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - React + TypeScript + Vite + TailwindCSSを使用したテンプレート +- [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - Vite、React、TypeScript、TailwindCSS、shadcn/uiを使用したテンプレート + +## Svelte + +- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - Svelteを使用したテンプレート +- [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - SvelteおよびViteを使用したテンプレート +- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - TailwindCSS v3を含んだ、SvelteおよびViteを使用したテンプレート +- [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - Svelte v4.2.0、Vite、TailwindCSS v3.3.3を使用したテンプレート +- [wails-sveltekit-template](https://github.com/h8gi/wails-sveltekit-template) - SvelteKitを使用したテンプレート + +## Solid + +- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-ts) - Solid + Ts + Viteを使用したテンプレート +- [wails-template-vite-solid-js](https://github.com/xijaja/wails-template-solid-js) - Solid + Js + Viteを使用したテンプレート + +## Elm + +- [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - 関数型プログラミングと**高速な**ホットリロードを使ったGUIアプリ開発 :tada: :rocket: +- [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - Elm + Tailwind CSS + Wailsのパワー:muscle:を組み合わせたテンプレート (ホットリロードサポートあり) + +## HTMX + +- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - インタラクティビティを実現するためのピュアなhtmxに、コンポーネントおよびフォームを作成するためのテンプレートが合わさったテンプレート + +## ピュアJavaScript (バニラ) + +- [wails-pure-js-template](https://github.com/KiddoV/wails-pure-js-template) - 基本的なJavaScript、HTML、CSSのみを含むテンプレート diff --git a/website/versioned_docs/version-v2.6.0/gettingstarted/_category_.json b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/_category_.json similarity index 100% rename from website/versioned_docs/version-v2.6.0/gettingstarted/_category_.json rename to website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/_category_.json diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx new file mode 100644 index 00000000000..dfab958b4e8 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx @@ -0,0 +1,22 @@ +--- +sidebar_position: 6 +--- + +# プロジェクトのコンパイル + +プロジェクトディレクトリ上で、`wails build`コマンドを実行しましょう。 そうすることで、プロジェクトがコンパイルされ、`build/bin`ディレクトリ内に本番配布用のバイナリが出力されます。 + +バイナリを起動すると、デフォルト仕様のアプリを確認することができます: + +```mdx-code-block +
+ +
+
+``` + +コンパイルオプションについて詳しくは、[CLIリファレンス](../reference/cli.mdx#build)をご覧ください。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx new file mode 100644 index 00000000000..5fbc7ab19cc --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx @@ -0,0 +1,16 @@ +--- +sidebar_position: 5 +--- + +# アプリの開発 + +プロジェクトディレクトリのルート上で`wails dev`コマンドを実行すると、アプリを開発モードで起動することができます。 コマンドを実行すると下記の処理が実行されます: + +- アプリをビルドしたのち、起動する +- Goのコードをフロントエンドにバインドして、JavaScriptから呼び出せるようにする +- [Vite](https://vitejs.dev/)の機能を使用して、Goファイルの変更を監視し、変更された際には自動的にリビルド/再起動する +- ブラウザからアプリを操作できるようにする[Webサーバ](http://localhost:34115)を立ち上げる。 これにより、任意のブラウザ拡張機能を利用できる。 JavascriptのコンソールからGoのコードを呼び出すこともできる + +アプリ開発を始めるときは、プロジェクトディレクトリ上で`wails dev`コマンドを実行しましょう。 詳しくは、[こちら](../reference/cli.mdx#dev)をご覧ください。 + +近日中にチュートリアルを公開予定です。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx new file mode 100644 index 00000000000..5dce70b33ea --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 2 +--- + +# プロジェクトの開始 + +## プロジェクトの生成 + +CLIのインストールが終わったら、`wails init`コマンドで新しいプロジェクトを生成しましょう。 + +好きなフレームワークを選択してください: + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + JavaScriptによるSvelteプロジェクトを生成する場合:

+ + wails init -n myproject -t svelte + +TypeScriptによるプロジェクトを生成する場合:
+ + wails init -n myproject -t svelte-ts + +
+ + JavaScriptによるReactプロジェクトを生成する場合:

+ + wails init -n myproject -t react + +TypeScriptによるプロジェクトを生成する場合:
+ + wails init -n myproject -t react-ts + +
+ + JavaScriptによるVueプロジェクトを生成する場合:

+ + wails init -n myproject -t vue + +TypeScriptによるプロジェクトを生成する場合:
+ + wails init -n myproject -t vue-ts + +
+ + JavaScriptによるPreactプロジェクトを生成する場合:

+ + wails init -n myproject -t preact + +TypeScriptによるプロジェクトを生成する場合:
+ + wails init -n myproject -t preact-ts + +
+ + JavaScriptによるLitプロジェクトを生成する場合:

+ + wails init -n myproject -t lit + +TypeScriptによるプロジェクトを生成する場合:
+ + wails init -n myproject -t lit-ts + +
+ + JavaScriptによるバニラなプロジェクトを生成する場合:

+ + wails init -n myproject -t vanilla + +TypeScriptによるプロジェクトを生成する場合:
+ + wails init -n myproject -t vanilla-ts + +
+
+``` + +
+ +様々な機能やフレームワークを提供する[コミュニティテンプレート](../community/templates.mdx)を利用することもできます。 + +プロジェクト生成時に使用可能なオプションを確認するには、`wails init -help`を実行してください。 詳しくは、[CLIリファレンス](../reference/cli.mdx#init)を参照してください。 + +## プロジェクトのディレクトリ構成 + +Wailsのプロジェクトディレクトリの構成は次のとおりです: + +``` +. +├── build/ +│ ├── appicon.png +│ ├── darwin/ +│ └── windows/ +├── frontend/ +├── go.mod +├── go.sum +├── main.go +└── wails.json +``` + +### プロジェクトの構造 + +- `/main.go` - アプリのメインコード +- `/frontend/` - フロントエンドのプロジェクトディレクトリ +- `/build/` - ビルドディレクトリ +- `/build/appicon.png` - アプリアイコン +- `/build/darwin/` - Mac固有のプロジェクトディレクトリ +- `/build/windows/` - Windows固有のプロジェクトディレクトリ +- `/wails.json` - プロジェクト構成ファイル +- `/go.mod` - Goモジュール定義ファイル +- `/go.sum` - Goモジュールチェックサムファイル + +`frontend`ディレクトリ内は、Wailsで決まったファイル構成等は無く、お好きなフロントエンドプロジェクトを配置することができます。 + +`build`ディレクトリは、アプリのビルド時に使用されます。 この中のファイルは、ビルドの挙動をカスタマイズするために、適宜ファイル内容を書き換えることができます。 buildディレクトリ内のファイルを削除すると、デフォルトのファイルが再生成されます。 + +`go.mod`のモジュール名は、最初は"changeme"になっています。 このモジュール名は、あなたのプロジェクトに適切な名前に変更しましょう。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx new file mode 100644 index 00000000000..bb00dbe8fd5 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx @@ -0,0 +1,89 @@ +--- +sidebar_position: 1 +--- + +# インストール + +## サポートされているプラットフォーム + +- Windows 10/11 AMD64/ARM64 +- MacOS 10.13+ AMD64 +- MacOS 11.0+ ARM64 +- Linux AMD64/ARM64 + +## 依存関係 + +Wailsをインストールする前に、下記のものを導入しておく必要があります。 + +- Go 1.18+ +- NPM (Node 15+) + +### Go + +[Goのダウンロードページ](https://go.dev/dl/)からGoをダウンロードしてください。 + +公式の[Goインストール手順](https://go.dev/doc/install)に従って、Goをインストールしてください。 その際、`PATH`環境変数に`~/go/bin`ディレクトリへのパスが含まれていることも確認してください。 それらが終わったら、ターミナルを再起動し、以下の確認をしてください: + +- Goが正しくインストールされているかを確認する: `go version` +- "~/go/bin"のディレクトリパスがPATH環境変数に含まれているか確認する: `echo $PATH | grep go/bin` + +### NPM + +[Nodeダウンロードページ](https://nodejs.org/ja/download/)からNPMをダウンロードしてください。 最新版を利用することをお勧めします。なぜなら、私たちは最新版に対してテストを実施しているためです。 + +`npm --version`を実行して、インストールが完了しているかを確認してください。 + +## プラットフォーム固有の依存関係 + +開発作業を行うプラットフォームによって、必要な依存関係が存在します: + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + Wailsを使用するには、xcodeのコマンドラインツールがインストールされている必要があります。 xcode-select --installコマンドを実行することでインストールできます。 + + + Wailsを使用するには、WebView2ランタイムがインストールされている必要があります。 最新のWindowsでは、すでにインストールされている場合もあります。 wails doctorコマンドで、インストール状況を確認できます。 + + + Linuxでは、標準のgccビルドツール、libgtk3libwebkitが必要です。 Wailsは、様々なディストリビューション向けに大量のコマンドを列挙することはせず、現在使用されているディストリビューションのインストールコマンドを自動的に判定します。 Wailsをインストールした後に、wails doctorコマンドを実行して、別途インストールが必要な依存関係を確認してください。 あなたが利用しているディストリビューションやパッケージマネージャーがサポートされていない場合は、Linuxディストリビューションサポートガイドを参照してください。 + + +``` + +## 任意の依存関係 + +- [UPX](https://upx.github.io/)を導入することで、構築したアプリを圧縮できます。 +- [NSIS](https://wails.io/docs/guides/windows-installer/)を導入することで、Windowsのインストーラを生成できます。 + +## Wailsのインストール + +`go install github.com/wailsapp/wails/v2/cmd/wails@latest`を実行して、Wails CLIをインストールしてください。 + +注意: 次のようなエラーが発生した場合: + +```shell +....\Go\pkg\mod\github.com\wailsapp\wails\v2@v2.1.0\pkg\templates\templates.go:28:12: pattern all:ides/*: no matching files found +``` +下記コマンドで、Go 1.18以上がインストールされているかを確認してください: +```shell +go version +``` + +## システムチェック + +`wails doctor`を実行すると、必要な依存関係が正しくインストールされているかを確認することができます。 正しくインストールされていない場合は、その内容をあなたにお知らせして、どうすれば解決できるかを教えてくれます。 + +## `wails`コマンドが見つからないのですが? + +`wails`コマンドが見つからないとシステムに怒られた場合は、Goが、公式のGoインストール手順に従って導入されているかを確認してください。 コマンドが見つからないほとんどの理由は、あなたのホームディレクトリ配下にある`go/bin`ディレクトリのパスが、`PATH`環境変数に含まれていないからです。 また、インストールによって行われた環境変更を反映させるために、もともと開いていたコマンドプロンプト(ターミナル)がある場合はそれらをいったん閉じて、再度開きなおしてください。 diff --git a/website/versioned_docs/version-v2.6.0/guides/_category_.json b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/_category_.json similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/_category_.json rename to website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/_category_.json diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx new file mode 100644 index 00000000000..2a049fd1e58 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx @@ -0,0 +1,14 @@ +# Angular + +Wailsでは、Angular向けのテンプレートは用意されていませんが、Angular自体を使用することはできます。 + +## 開発モード + +Angularで開発モードを使用するには、`wails.json`で下記のように設定してください: + +```json + "frontend:build": "npx ng build", + "frontend:install": "npm install", + "frontend:dev:watcher": "npx ng serve", + "frontend:dev:serverUrl": "http://localhost:4200", +``` \ No newline at end of file diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx new file mode 100644 index 00000000000..850d85f382b --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx @@ -0,0 +1,215 @@ +# アプリケーション開発 + +Wailsでアプリケーションを作成する際に、厳格なルールはありませんが、基本的なガイドラインがいくつかあります。 + +## アプリケーションセットアップ + +デフォルトのテンプレートを使用した場合、`main.go`にはアプリケーションの構成および起動コードが記述され、`app.go`にはアプリケーションのロジック定義が記述されています。 + +`app.go`ファイルには、メインアプリケーションのフックとして機能する2つのメソッドを持った構造体を定義します。 + +```go title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} +``` + +- startupメソッドは、Wailsが起動時に、必要リソースの割り当てが完了した際にすぐに呼び出されます。このメソッド内は、リソースの作成、イベントリスナーの設定、その他アプリケーションに必要な初期処理を実施するのに適しています。 メソッド呼び出し時に与えられる`context.Context`は、通常は、構造体のフィールドに格納するようにしてください。 なぜならば、このcontextは[runtime](../reference/runtime/intro.mdx)を呼び出す際に必要なためです。 このstartupメソッドがエラーを返却した場合、アプリケーションは終了します。 開発モードの場合、コンソールにエラーが出力されます。 + +- shutdownメソッドは、シャットダウンプロセスの最後に、Wailsによって呼び出されます。 このメソッド内は、メモリを解放し、任意のシャットダウンタスクを実施するのに適しています。 + +通常、`main.go`ファイルでは、アプリケーション構成を受け取る`wails.Run()`メソッドを1回だけ呼び出すようにします。 テンプレートでは、`wails.Run()`を呼び出す前に、`app.go`で定義した構造体のインスタンスを作成して、`app`に格納しています。 アプリケーション構成では、コールバックを追加できます: + +```go {3,9,10} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +アプリケーションのライフサイクルフックについて詳しくは、[こちら](../howdoesitwork.mdx#application-lifecycle-callbacks)をご覧ください。 + +## メソッドのバインディング + +フロントエンドからGoのメソッドを呼び出したいことがありますよね。 そのようなときは、`app.go`ですでに定義している構造体に、パブリックメソッドを追加しましょう: + +```go {16-18} title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +アプリケーション構成の`Bind`キーで、Wailsに何をバインドさせたいかを指定できます: + +```go {11-13} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +これにより、`App`構造体のすべてのパブリックメソッドがバインドされます(startupメソッド・shutdownメソッドはバインドされません)。 + +### 複数の構造体をバインドするときのcontextの扱い + +もし、複数の構造体のメソッドをバインドしたくて、かつ、各構造体でランタイム関数を呼び出せるようにcontextを共有したい場合は、`OnStartup`のコールバック内で、各構造体にcontextを渡してあげるのが良いでしょう: + +```go +func main() { + + app := NewApp() + otherStruct := NewOtherStruct() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: func(ctx context.Context){ + app.SetContext(ctx) + otherStruct.SetContext(ctx) + }, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + otherStruct + }, + }) + if err != nil { + log.Fatal(err) + } +} +``` + +バインディングの詳細については、[こちら](../howdoesitwork.mdx#method-binding)をご覧ください。 + +## アプリケーションメニュー + +Wailsでは、アプリケーションにメニューを追加することができます。 追加したい場合は、アプリケーション構成に[Menu](../reference/menus.mdx#menu)構造体を渡してください。 通常は、Menuを返すようなメソッドを使用するようにします。ライフサイクルフックに使用される`App`構造体のメソッドとして用意するのが良いでしょう。 + +```go {11} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Menu: app.menu(), + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +## アセット + +Wails v2にアセットを処理させるための方法は複雑ではありません。 Wailsに与える必要があるのは、`embed.FS`だけです。 任意の方法で与えてあげてください。 バニラテンプレートで使用されているように、素のhtml/css/jsファイルをアセットとして使用できます。 もちろん、複雑なビルドシステムを使用することも可能ですが、必須要件ではありません。 + +`wails build`コマンドを実行すると、プロジェクトルートディレクトリに存在するプロジェクト構成ファイルである`wails.json`のチェックが行われます。 プロジェクトファイルには、次の2つのキーを含めることができます: + +- "frontend:install" +- "frontend:build" + +1番目のキーは、`frontend`ディレクトリにおいて、nodeモジュールをインストールするためのコマンドを指定します。 2番目のキーは、`frontend`ディレクトリにおいて、フロントエンドをビルドするためのコマンドを指定します。 + +2つのキーのどちらともが指定されていない場合、Wailsはフロントエンドプロジェクトに対する操作を一切行いません。 `embed.FS`で指定されたディレクトリを参照するのみとなります。 + +### アセットハンドラ + +Wails v2では必要に応じて、`options.App`の中に`http.Handler`を定義することができます。これにより、アセットサーバにフックして、その場でファイルを作成したり、POST/PUTリクエストを処理したりすることができます。 GETリクエストが要求されたときは、まず初めに、`assets` FSにハンドリングされます。 リクエストされたファイルをFSが見つけられなかった場合、そのリクエストは`http.Handler`に転送されます。 GET以外のリクエストは、`AssetsHandler`が指定されていれば、当該ハンドラによって直接処理されます。 なお、`Assets`オプションに`nil`を指定することで、`AssetsHandler`のみを使用することも可能です。 + +## ビルトイン開発サーバ + +`wails dev`コマンドを実行すると、ビルトイン開発サーバが起動し、プロジェクトディレクトリ内のファイル監視が開始されます。 デフォルトでは、ファイルの中身が変更された場合、Wailsはそのファイルがアプリケーションファイルであるかどうかをチェックします(デフォルト: `.go`、 `-e`フラグで制御可能)。 アプリケーションファイルであった場合は、アプリケーションをリビルドして再起動します。 アセットディレクトリ内でファイルが変更された場合は、少し経ってからリロードが実行されます。 + +開発サーバは"デバウンシング"と呼ばれるテクニックを使用しています。これにより、短時間で複数のファイルが更新されたとしても、すぐに再読み込みされることはありません。 トリガーが起動すると、再読み込みを実行する前に一定時間待機します。 待機中に別のトリガーが起動した場合、待機時間はリセットされます。 デフォルトでは、待機時間は`100ms`です。 この待機時間の値があなたのプロジェクトで適切ではない場合、`-debounce`フラグを使用して変更することができます。 このフラグを使用すると、値がプロジェクト構成ファイルに保存され、次回以降のデフォルト値となります。 + +## 外部開発サーバ + +フレームワークによっては独自のライブリロードサーバが付属しているものがありますが、それらはWailsのGoバインディングを使用することができません。 このような場面では、Wailsが監視するビルドディレクトリ内で、プロジェクトをリビルドする監視スクリプトを実行すると良いでしょう。 例としては、[rollup](https://rollupjs.org/guide/en/)を使用するデフォルトのsvelteテンプレートをご覧ください。 + +### Create React App + +The process for a Create-React-App project is slightly more complicated. In order to support live frontend reloading the following configuration needs to be added to your `wails.json`: + +```json + "frontend:dev:watcher": "yarn start", + "frontend:dev:serverUrl": "http://localhost:3000", +``` + +The `frontend:dev:watcher` command will start the Create-React-App development server (hosted on port `3000` typically). The `frontend:dev:serverUrl` command then instructs Wails to serve assets from the development server when loading the frontend rather than from the build folder. In addition to the above, the `index.html` needs to be updated with the following: + +```html + + + + + +``` + +This is required as the watcher command that rebuilds the frontend prevents Wails from injecting the required scripts. This circumvents that issue by ensuring the scripts are always injected. With this configuration, `wails dev` can be run which will appropriately build the frontend and backend with hot-reloading enabled. Additionally, when accessing the application from a browser the React developer tools can now be used on a non-minified version of the application for straightforward debugging. Finally, for faster builds, `wails dev -s` can be run to skip the default building of the frontend by Wails as this is an unnecessary step. + +## Goモジュール + +デフォルトのWailsテンプレートは、モジュール名が"changeme"となっている`go.mod`ファイルを生成します。 プロジェクトの生成が完了したら、適切なモジュール名に変更してください。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx new file mode 100644 index 00000000000..fd81a974d04 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx @@ -0,0 +1,66 @@ +# Crossplatform build with Github Actions + +To build a Wails project for all the available platforms, you need to create an application build for each operating system. One effective method to achieve this is by utilizing GitHub Actions. + +An action that facilitates building a Wails app is available at: +https://github.com/dAppServer/wails-build-action + +In case the existing action doesn't fulfill your requirements, you can select only the necessary steps from the source: +https://github.com/dAppServer/wails-build-action/blob/main/action.yml + +Below is a comprehensive example that demonstrates building an app upon the creation of a new Git tag and subsequently uploading it to the Actions artifacts: + +```yaml +name: Wails build + +on: + push: + tags: + # Match any new tag + - '*' + +env: + # Necessary for most environments as build failure can occur due to OOM issues + NODE_OPTIONS: "--max-old-space-size=4096" + +jobs: + build: + strategy: + # Failure in one platform build won't impact the others + fail-fast: false + matrix: + build: + - name: 'App' + platform: 'linux/amd64' + os: 'ubuntu-latest' + - name: 'App' + platform: 'windows/amd64' + os: 'windows-latest' + - name: 'App' + platform: 'darwin/universal' + os: 'macos-latest' + + runs-on: ${{ matrix.build.os }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Build wails + uses: dAppServer/wails-build-action@v2.2 + id: build + with: + build-name: ${{ matrix.build.name }} + build-platform: ${{ matrix.build.platform }} + package: false + go-version: '1.20' +``` + +This example offers opportunities for various enhancements, including: + +- Caching dependencies +- Code signing +- Uploading to platforms like S3, Supbase, etc. +- Injecting secrets as environment variables +- Utilizing environment variables as build variables (such as version variable extracted from the current Git tag) diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx new file mode 100644 index 00000000000..e86b651845d --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx @@ -0,0 +1,204 @@ +# Custom Protocol Scheme association + +Custom Protocols feature allows you to associate specific custom protocol with your app so that when users open links with this protocol, +your app is launched to handle them. This can be particularly useful to connect your desktop app with your web app. +In this guide, we'll walk through the steps to implement custom protocols in Wails app. + +## Set Up Custom Protocol Schemes Association: + +To set up custom protocol, you need to modify your application's wails.json file. +In "info" section add a "protocols" section specifying the protocols your app should be associated with. + +For example: + +```json +{ + "info": { + "protocols": [ + { + "scheme": "myapp", + "description": "My App Protocol", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------ | +| scheme | Custom Protocol scheme. e.g. myapp | +| description | Windows-only. The description. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open custom protocol with your app, the system will launch your app and call the `OnUrlOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnUrlOpen: func(url string) { println(url) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows Custom Protocol Schemes is supported only with NSIS installer. During installation, the installer will create a +registry entry for your schemes. When you open url with your app, new instance of app is launched and url is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there (note that `%u` is important in Exec). Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=x-scheme-handler/myapp; +``` + +2. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +``` + +3. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with custom protocol scheme. When you open url with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx new file mode 100644 index 00000000000..a765cff58f6 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx @@ -0,0 +1,136 @@ +# 動的アセット + +[AssetsHandler](../reference/options#assetshandler)オプションを使用することで、フロントエンドアセットを動的に読み込んだり生成させることができます。 AssetsHandlerは、ジェネリックな`http.Handler`です。アセットサーバへのGET以外のすべてのリクエスト、および、アセットファイルとして存在しなかったがために転送されてきたGETリクエストに対して、ハンドラが呼び出されます。 + +カスタムされたAssetsHandlerを導入すると、カスタムアセットサーバを使用して独自のアセットを提供することができます。 + +## 例 + +このサンプルプロジェクトでは、ディスクからファイルを読み込むシンプルなアセットハンドラを作成します: + +```go title=main.go {17-36,49} +package main + +import ( + "embed" + "fmt" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "net/http" + "os" + "strings" +) + +//go:embed all:frontend/dist +var assets embed.FS + +type FileLoader struct { + http.Handler +} + +func NewFileLoader() *FileLoader { + return &FileLoader{} +} + +func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) { + var err error + requestedFilename := strings.TrimPrefix(req.URL.Path, "/") + println("Requesting file:", requestedFilename) + fileData, err := os.ReadFile(requestedFilename) + if err != nil { + res.WriteHeader(http.StatusBadRequest) + res.Write([]byte(fmt.Sprintf("Could not load file %s", requestedFilename))) + } + + res.Write(fileData) +} + +func main() { + // App構造体のインスタンスを作成 + app := NewApp() + + // オプション付きでアプリケーションを作成 + err := wails.Run(&options.App{ + Title: "helloworld", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: NewFileLoader(), + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 255}, + OnStartup: app.startup, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +`wails dev`コマンドでアプリケーションを開発モードで実行すると、次のように出力されます: + +``` +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' failed, using AssetHandler +Requesting file: favicon.ico +``` + +これを見ると分かるように、アセットハンドラは、デフォルトのアセットサーバが`favicon.ico`を提供できない場合に呼び出されています。 + +メインアプリケーションをクリックし、"検証(開発者ツールで調査する)"を選択して、開発者ツールを起動します。そして、コンソールに次のように入力して実行することで、機能をテストできます: + +``` +let response = await fetch('does-not-exist.txt'); +``` + +これにより、開発者ツールでエラーが発生します。 カスタムアセットハンドラによって、想定どおりのエラーが返却されていることが分かります。 + +```mdx-code-block +

+ +

+``` + +もし、`go.mod`をリクエストした場合は、次のような出力となります: + +```mdx-code-block +

+ +

+``` + +このテクニックを使用して、ページ上に画像を直接読み込ませることができます。 デフォルトのバニラテンプレートで、ロゴ画像を指定している、下記コードを、 + +```html + +``` + +次のように書き換えます: + +```html + +``` + +すると、画面上は次のような表示となります: + +```mdx-code-block +

+ +

+``` + +:::warning + +この例のようにファイルシステムを公開することは、セキュリティ上のリスクとなります。 ファイルシステムへのアクセスは、適切に管理することを推奨します。 + +::: diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx new file mode 100644 index 00000000000..167955b12d7 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx @@ -0,0 +1,244 @@ +# File Association + +File association feature allows you to associate specific file types with your app so that when users open those files, +your app is launched to handle them. This can be particularly useful for text editors, image viewers, or any application +that works with specific file formats. In this guide, we'll walk through the steps to implement file association in Wails app. + +## Set Up File Association: + +To set up file association, you need to modify your application's wails.json file. +In "info" section add a "fileAssociations" section specifying the file types your app should be associated with. + +For example: + +```json +{ + "info": { + "fileAssociations": [ + { + "ext": "wails", + "name": "Wails", + "description": "Wails Application File", + "iconName": "wailsFileIcon", + "role": "Editor" + }, + { + "ext": "jpg", + "name": "JPEG", + "description": "Image File", + "iconName": "jpegFileIcon", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | +| ext | The extension (minus the leading period). e.g. png | +| name | The name. e.g. PNG File | +| iconName | The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows | +| description | Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open file (or files) with your app, the system will launch your app and call the `OnFileOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnFileOpen: func(filePaths []string) { println(filestring) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows file association is supported only with NSIS installer. During installation, the installer will create a +registry entry for your file associations. When you open file with your app, new instance of app is launched and file path is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there. Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=application/x-wails;application/x-test +``` + +2. Create mime types file. Example: + +```xml + + + + Wails Application File + + + +``` + +3. Create icons for your file types. SVG icons are recommended. +4. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload mime types to register file associations +update-mime-database /usr/share/mime +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +# update icons +update-icon-caches /usr/share/icons/* +``` + +5. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ./application-wails-mime.xml + dst: /usr/share/mime/packages/application-x-wails.xml +- src: ./application-test-mime.xml + dst: /usr/share/mime/packages/application-x-test.xml +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with specified file types. When you open file with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx new file mode 100644 index 00000000000..b6218d81e1e --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx @@ -0,0 +1,87 @@ +# フレームレスアプリケーション + +Wailsでは、フレームのないアプリケーションの作成をサポートしています。 [アプリケーションオプション](../reference/options.mdx#application-options)の[frameless](../reference/options.mdx#frameless)フィールドで設定することが可能です。 + +Wailsでは、フレームレスウィンドウをドラッグできるようにするための簡単な仕組みを提供しています。`--wails-draggable:drag`というCSSスタイルをもつ任意のHTML要素は、"ドラッグハンドル"として機能します。 このプロパティは、すべての子要素にも継承されます。 ネストされている子要素で、ドラッグを明示的に無効化したい場合は、当該子要素で'--wails-draggable:no-drag'を指定します。 + +```html + + + + + + + +
+ + +
+
+ + + + +``` + +一部のプロジェクトでは、動的なスタイリングが原因で、これらのCSSプロパティが使用できない場合があるでしょう。 そのような場合、アプリケーションオプションの`CSSDragProperty`および`CSSDragValue`を使用して、ドラッグ可能な領域を示すプロパティ名と値を独自に定義することができます。 + +```go title=main.go +package main + +import ( + "embed" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + // アプリケーション構造体のインスタンスを作成 + app := NewApp() + + // オプション付きでアプリケーションを作成 + err := wails.Run(&options.App{ + Title: "alwaysontop", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Frameless: true, + CSSDragProperty: "widows", + CSSDragValue: "1", + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +```html title=index.html + + + + + + alwaysontop + + +
+ + + +``` + +:::info フルスクリーン + +アプリケーションをフルスクリーン状態にすると、このドラッグ機能は無効になります。 + +::: diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx new file mode 100644 index 00000000000..2d976fbf741 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx @@ -0,0 +1,72 @@ +# フロントエンド + +## スクリプトの注入 + +Wailsが`index.html`を提供するとき、デフォルトでは、``タグ内に`/wails/ipc.js`および`/wails/runtime.js`の2つのスクリプトを読み込む行を注入します。 これらのスクリプトファイルは、バインディングおよびランタイムを提供しています。 + +デフォルトでどの位置にスクリプトが注入されるかを、下記のコードに示します: + +```html + + + injection example + + + + + + + +
Please enter your name below 👇
+
+ + +
+ + + + +``` + +### デフォルトのスクリプト注入の上書き + +開発者がより柔軟に対応できるように、これらの動作をカスタマイズするためのメタタグが用意されています: + +```html + +``` + +オプションは次のとおりです: + +| 値 | 説明 | +| ------------------- | ------------------------------- | +| noautoinjectruntime | `/wails/runtime.js`の自動注入を無効化します | +| noautoinjectipc | `/wails/ipc.js`の自動注入を無効化します | +| noautoinject | すべてのスクリプトの自動注入を無効化します | + +カンマで区切ることで、複数のオプションを指定できます。 + +次のコードは、自動注入版のコードと完全に同じ挙動となります: + +```html + + + injection example + + + + + + +
Please enter your name below 👇
+
+ + +
+ + + + + + +``` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx new file mode 100644 index 00000000000..daf0c4802fa --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx @@ -0,0 +1,127 @@ +# 統合開発環境 + +Wailsでは、優れた開発体験の提供を目指しています。 その一環として、統合開発環境特有の構成設定の生成をサポートしており、より快適にプロジェクトをセットアップできるようになっています。 + +現在は[Visual Studio Code](https://code.visualstudio.com/)をサポートしていますが、今後、Golandなど他の統合開発環境もサポートしていく予定です。 + +## Visual Studio Code + +```mdx-code-block +

+ +

+``` + +プロジェクト生成時のコマンドに`-ide vscode`フラグを付与すると、統合開発環境用の構成ファイルが、他のプロジェクトファイルと共に作成されます。 これらのファイルは`.vscode`ディレクトリ内に配置され、アプリケーションをデバッグするための正しい構成設定が記述されています。 + +生成されるのは`tasks.json`ファイルおよび`launch.json`ファイルの2つです。 デフォルトのバニラプロジェクトの場合、次のような内容となります: + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/myproject.exe" + ] + } + ] +} +``` + +```json title="launch.json" +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Wails: Debug myproject", + "type": "go", + "request": "launch", + "mode": "exec", + "program": "${workspaceFolder}/build/bin/myproject.exe", + "preLaunchTask": "build", + "cwd": "${workspaceFolder}", + "env": {} + } + ] +} +``` + +### インストールおよびビルドステップの構成 + +デフォルトのプロジェクトでは、`npm install`や`npm run build`などのステップが必要ないため、`tasks.json`ファイルの内容なシンプルなものになっています。 Svelteテンプレートのように、フロントエンドのビルドステップが必要なプロジェクトの場合、`tasks.json`を編集して、インストールおよびビルドのステップを追加する必要があります。 + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "npm install", + "type": "npm", + "script": "install", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "npm run build", + "type": "npm", + "script": "build", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/vscode.exe" + ], + "dependsOn": ["npm install", "npm run build"] + } + ] +} +``` + +今後の機能強化予定 + +将来的に、インストールおよびビルドステップを含んだ`tasks.json`を自動生成できるように計画しています。 + +::: diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx new file mode 100644 index 00000000000..4d9b9640025 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx @@ -0,0 +1,103 @@ +# Linuxディストリビューションサポート + +## 概要 + +WailsはLinuxをサポートしていますが、すべてのLinuxディストリビューションに対してインストール手段を提供することは困難であるため、行っていません。 その代わりにWailsでは、アプリケーション開発に必要なパッケージが、システムのパッケージマネージャを介して利用可能かどうかを判断します。 現在、以下のパッケージマネージャをサポートしています: + +- apt +- dnf +- emerge +- eopkg +- nixpkgs +- pacman +- zypper + +## パッケージ名の追加 + +あなたが使用しているディストリビューションが、Wailsがサポートしているパッケージマネージャを使用していたとしても、パッケージ名が想定と異なっている場合があります。 例えば、Ubuntuの派生ディストリビューションを使用している場合、gtkのパッケージ名が異なる場合があります。 Wailsは、パッケージ名のリストを繰り返し処理することで、正しいパッケージを見つけようと試みます。 パッケージ名のリストは、`v2/internal/system/packagemanager`ディレクトリ内に、パッケージマネージャごとのファイルで格納されています。 下記は、`v2/internal/system/packagemanager/apt.go`の例です。 + +このファイルでは、パッケージのリストは`Packages()`メソッドによって定義されています: + +```go +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +お使いのLinuxディストリビューションが、`libgtk-3`パッケージが`lib-gtk3-dev`という名前で配布されていると仮定しましょう。 その場合、次の行を追加することで、対応することができます: + +```go {5} +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + {Name: "lib-gtk3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +## パッケージマネージャの追加 + +新しいパッケージマネージャを追加するには、次の手順を実行します: + +- `v2/internal/system/packagemanager`に、`.go`という名前の新しいファイルを作成します。``はパッケージマネージャの名前です。 +- `pm.go`の中で、PackageManagerインターフェースを実装した構造体を定義します: + +```go +type PackageManager interface { + Name() string + Packages() packagemap + PackageInstalled(*Package) (bool, error) + PackageAvailable(*Package) (bool, error) + InstallCommand(*Package) string +} +``` + +- `Name()`メソッドで、パッケージマネージャの名前を返すように実装します。 +- `Packages()`メソッドで、依存関係の候補ファイル名を提供する`packagemap`を返すように実装します。 +- `PackageInstalled()`メソッドで、引数で渡されたパッケージがすでにインストールされている場合は`true`を返すように実装します。 +- `PackageAvailable()`メソッドで、引数で指定されたパッケージがインストールはされていないけれどもインストール可能であるなら`true`を返すように実装します。 +- `InstallCommand()`メソッドで、引数で指定されたパッケージをインストールするための正確なコマンドを返すように実装します。 + +他のパッケージマネージャのコードを参考にして、これらのコードがどのように動作するか把握してください。 + +:::info リマインド + +新しいパッケージマネージャを追加した場合は、このページも忘れずに更新してください。 + +::: diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx new file mode 100644 index 00000000000..e726244fc6e --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx @@ -0,0 +1,18 @@ +# Linux + +このページでは、Linux向けのWailsアプリケーション開発に関する、様々なガイドを掲載しています。 + +## videoタグが"ended"イベントを発火しない + +videoタグを使用している場合、ビデオの再生が終了しても"ended"イベントが発火しません。 これはWebkitのバグであり、次のような回避策を講じることで修正できます: + +```js +videoTag.addEventListener("timeupdate", (event) => { + if (event.target.duration - event.target.currentTime < 0.2) { + let ended = new Event("ended"); + event.target.dispatchEvent(ended); + } +}); +``` + +出典: [ディスカッションボード](https://github.com/wailsapp/wails/issues/1729#issuecomment-1212291275)における[Lyimmi](https://github.com/Lyimmi)のコメント diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx new file mode 100644 index 00000000000..f01fba42878 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx @@ -0,0 +1,55 @@ +# ローカル開発 + +## 概要 + +Wailsは現在も継続的に開発されており、定期的に、新しいリリースに対して"タグ付け"が行われています。 "タグ付け"は通常、`master`ブランチに存在する新しいコードがすべてテストされ、正常な動作が確認されたときに行われます。 まだリリースされていない新機能やバグフィックスを利用したい場合、以下の手順で"ブリーディング・エッジ"版を使用できます: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails/v2/cmd/wails` +- `go install` + +注意: このページでは、Wailsプロジェクトをクローンしたディレクトリのことを"clonedir"と記します。 + +この手順により、Wails CLIは一番最新のバージョンとなります。 + +### 自身のプロジェクトの更新 + +クローンした最新バージョンのWailsライブラリを自身のプロジェクトで使用させたい場合、`go.mod`ファイルの末尾に次の行を追記してください: + +`replace github.com/wailsapp/wails/v2 => ` + +例: + +Windowsの場合: `replace github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2` + +'nixの場合: `replace github.com/wailsapp/wails/v2 => /home/me/projects/wails/v2` + +安定バージョンに戻す場合は、次のコマンドを実行します: + +`go install github.com/wailsapp/wails/v2/cmd/wails@latest` + +## ブランチのテスト + +先述の手順に従えば、ブランチをテストすることができますが、インストールを実行する前に、テスト対象のブランチに切り替えるようにしてください: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails` +- `git checkout -b branch-to-test --track origin/branch-to-test` +- `cd v2/cmd/wails` +- `go install` + +そして、先述のとおり[自身のプロジェクトを更新](#updating-your-project)してください。 + +## プルリクエストのテスト + +先述の手順に従えば、プルリクエストをテストすることができますが、インストールを実行する前に、テスト対象のプルリクエストを取得してブランチを切り替えるようにしてください。 下記手順の`[IDofThePR]`の部分は、github.comで表示されているプルリクエストのIDに置き換えてください: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails` +- `git fetch -u origin pull/[IDofThePR]/head:test/pr-[IDofThePR]` +- `git checkout test/pr-[IDofThePR]` +- `git reset --hard HEAD` +- `cd v2/cmd/wails` +- `go install` + +そして、先述のとおり[自身のプロジェクトを更新](#updating-your-project)してください。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx new file mode 100644 index 00000000000..b9cbf912aa2 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx @@ -0,0 +1,97 @@ +# Mac App Storeガイド + +このページでは、WailsアプリをMac App Storeで公開する方法について、概要を説明します。 + +## 前提条件 + +- Apple Developerアカウントを所持しておく必要があります。 詳しくは、[Apple Developer Program](https://developer.apple.com/support/compare-memberships/)のサイトを確認してください。 +- 開発者ポータルで、証明書、ID、アプリを作成しておく必要があります。 詳しくは以下の手順に従ってください。 +- Xcodeコマンドラインツールを、あなたのローカルマシンにインストールしておく必要があります。 + +#### 証明書とIDの作成 + +1. [Apple Developerアカウント](https://developer.apple.com/account/)へアクセスします。 +2. `Certificates, Identifiers & Profiles`内にある`Identifiers`をクリックし、新しいApp IDを登録します。 (com.example.app) のような形式にしてください。 +3. 同じページで`Certificates`をクリックし、Mac App Storeディストリビューション用の新しい証明書を生成します。 それらの証明書をダウンロードし、ローカルマシンのKeychainにインポートしてください。 + +#### アプリ提出物の作成 + +1. [App Store Connectサイト](https://appstoreconnect.apple.com/apps)へアクセスします。 +2. 新しいアプリケーションを登録し、前のステップで作成済みのバンドルIDをリンクします。 +3. Appleの要求する正規のスクリーンショットや説明文などを、アプリに追加します。 +4. アプリの新しいバージョンを作成します。 + +#### プロビジョニングプロファイルの作成 +1. [Apple Developerプロフィール](https://developer.apple.com/account/resources/profiles/list)ページへアクセスします。 +2. Mac App Storeへの配布用に、新しいプロビジョニングプロファイルを追加します。 +3. プロファイルタイプをMacに設定し、先ほど作成したアプリケーションのApp IDを選択します。 +4. Mac App Distribution証明書を選択します。 +5. 埋め込みプロビジョニングプロファイルに名前をつけ、作成されたプロファイルをダウンロードします。 + +## Mac App Storeへの公開手順 + +#### AppleのApp Sandboxの有効化 + +Mac App Storeへ提出されるアプリは、Appleの[App Sandbox](https://developer.apple.com/app-sandboxing/)内で動作する必要があります。 そのためには、`entitlements.plist`ファイルを作成しておく必要があります。 ファイルは、`{PROJECT_DIR}/build/darwin/entitlements.plist`配下に作成することを推奨します。 + +**entitlementsファイルの例** + +ここでは、[RiftShare](https://github.com/achhabra2/riftshare)というアプリのentitlementsファイルを例として示します。 参考として、アプリが必要とする権限を入力してください。 詳しくは、[こちらのサイト](https://developer.apple.com/documentation/bundleresources/entitlements)をご覧ください。 チーム ID とアプリケーション名を上記で登録したものに置き換える必要があります。 + +```xml title="entitlements.plist" + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + com.apple.application-identifier + TEAM_ID.APP_NAME + com.apple.developer.team-identifier + TEAM_ID + + +``` + +**組み込みプロビジョニング プロファイルの追加** 上記で作成したプロビジョニング プロファイルは、アプリケーションのルートに追加する必要があります。 embedded.provisionprofile という名前にする必要があります。 + +#### アプリパッケージのビルドと署名 + +以下は、Mac App Storeへの提出用に、アプリをビルドおよび署名するスクリプトの例です。 プロジェクトのルートディレクトリからスクリプトを実行することを前提としています。 + +アプリへ署名するための証明書と、インストーラへ署名するための証明書は異なりますので、ご注意ください。 両方の証明書がKeychainにインポートされていることを確認してください。 Keychainで文字列を探し、下記スクリプトに挿入してください。 具体的には、証明書名およびアプリ名を入力します。 以下のスクリプトを実行すると、アプリケーションのルートディレクトリに、署名済みの`app.pkg`ファイルが生成されます。 + +```bash title="macappstore-build.sh" +#!/bin/bash + +APP_CERTIFICATE="3rd Party Mac Developer Application: YOUR NAME (CODE)" +PKG_CERTIFICATE="3rd Party Mac Developer Installer: YOUR NAME (CODE)" +APP_NAME="YourApp" + +wails build -platform darwin/universal -clean + +cp ./embedded.provisionprofile "./build/bin/$APP_NAME.app/Contents" + +codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist ./build/bin/$APP_NAME.app + +productbuild --sign "$PKG_CERTIFICATE" --component ./build/bin/$APP_NAME.app /Applications ./$APP_NAME.pkg +``` + +#### アプリバンドルのアップロード + +審査向けに提出が可能となる前に、生成されたパッケージファイルをアップロードし、アプリケーションに関連付ける必要があります。 + +1. Mac App Storeから[Transporter App](https://apps.apple.com/us/app/transporter/id1450874784)をダウンロードします。 +2. アプリを起動し、Apple IDでサインインします。 +3. +マークをクリックし、前のステップで生成済みの`APP_NAME.pkg`ファイルを選択します。 そしてアップロードします。 +4. [App Store Connect](https://appstoreconnect.apple.com/apps)サイトへ戻り、アプリ提出物ページへ戻ります。 App Storeで公開する準備できているバージョンを選択します。 `Build`内で、Transporter経由でアップロードしたパッケージを選択します。 + +以上で終了です! サイトで、アプリを審査のために提出できるようになりました。 数営業日後、審査結果に問題が無ければ、アプリがMac App Storeに公開されます。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx new file mode 100644 index 00000000000..884f9e8c3a0 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx @@ -0,0 +1,95 @@ +# 手動ビルド + +Wails CLIは、プロジェクトに関する様々な面倒な作業を担ってくれていますが、ときにはプロジェクトを手動でビルドできたほうが望ましい場合もあるでしょう。 このドキュメントでは、CLIが実行する多くの操作や、これらの操作を別の手段で実現するための方法について説明します。 + +## ビルドプロセス + +Wails CLIは、`wails build`コマンドまたは`wails dev`コマンドが使用されると、共通のビルドプロセスを実行します: + + - フロントエンド依存関係のインストール + - フロントエンドのビルド + - ビルドアセットの生成 + - アプリケーションのコンパイル + - [任意] アプリケーションの圧縮 + +### フロントエンド依存関係のインストール + +#### CLIが実行する手順 + +- `-s`フラグが指定された場合、この手順をスキップします。 +- `wails.json`ファイル内で、`frontend:install`キーにインストールコマンドが記述されているかを確認します。 +- 記述されていない場合、この手順をスキップします。 +- 記述されている場合、フロントエンドディレクトリ内に`package.json`ファイルが存在するか確認します。 存在しない場合、この手順をスキップします。 +- `package.json`ファイルの内容をもとに、MD5チェックサムを生成します。 +- `package.json.md5`ファイルが存在するか確認し、存在する場合は、さきほど生成したMD5チェックサムと比較して、内容が変更されていないかどうかを確認します。 内容が同じ場合、この手順をスキップします。 +- `package.json.md5`ファイルが存在しない場合、ファイルを作成し、さきほど生成したMD5チェックサムを書き込みます。 +- この時点でビルドが必要と判断された場合、`node_modules`ディレクトリが存在しない場合、または`-f`フラグが指定された場合は、フロントエンドディレクトリ内でインストールコマンドを実行します。 + +#### 手動で実行する手順 + +コマンドライン、または`npm install`のスクリプトを用いて、この手順を実行してください。 + +### フロントエンドのビルド + +#### Wails CLIでの手順 + +- `-s`フラグが指定された場合、この手順をスキップします。 +- `wails.json`ファイル内で、`frontend:build`キーにビルドコマンドが記述されているかを確認します。 +- 記述されていない場合、この手順をスキップします。 +- 記述されている場合、フロントエンドディレクトリ内でコマンドが実行されます。 + +#### 手動で実行する手順 + +コマンドライン、`npm run build`のスクリプト、またはフロントエンドのビルドスクリプトを用いて、この手順を実行してください。 + +### アセットの生成 + +#### Wails CLIでの手順 + +- `-nopackage`フラグが指定された場合、この手順をスキップします。 +- `build/appicon.png`ファイルが存在しない場合、デフォルトのファイルを作成します。 +- Windowsの場合、[Windowsバンドル](#windows)の節を参照してください。 +- `build/windows/icon.ico`ファイルが存在しない場合、`build/appicon.png`画像ファイルから新規作成します。 + +##### Windows + +- `build/windows/icon.ico`ファイルが存在しない場合、`build/appicon.png`ファイルをもとに、256、128、64、48、32、16サイズのアイコンを新規作成します。 この処理は[winicon](https://github.com/leaanthony/winicon)によって実現しています。 +- `build/windows/.manifest`ファイルが存在しない場合、デフォルトバージョンから新規作成します。 +- アプリケーションを本番ビルドとしてコンパイルします(上記のとおり)。 +- [winres](https://github.com/tc-hib/winres)を使用して、アイコンとマニフェストをリンクできる`.syso`ファイルにバンドルします。 + +#### 手動で実行する手順 + +- [winicon](https://github.com/leaanthony/winicon)のCLIツール(または他の任意ツール)を使用して、`icon.ico`を作成します。 +- アプリケーションの`.manifest`ファイルを作成または更新します。 +- [winres CLI](https://github.com/tc-hib/go-winres)を使用して、`.syso`ファイルを生成します。 + +### アプリケーションのコンパイル + +#### Wails CLIでの手順 + +- `-clean`フラグが指定された場合、`build`ディレクトリを削除して再作成します。 +- `wails dev`コマンドの場合、デフォルトで次のGoフラグを使用するようにします: `-tags dev -gcflags "all=-N -l"` +- `wails build`コマンドの場合、デフォルトで次のGoフラグを使用するようにします: `-tags desktop,production -ldflags "-w -s"` + - Windowsの場合: `-ldflags "-w -h -H windowsgui"` +- `-tags`フラグを使用してCLIに指定された追加タグを、デフォルトのタグに追記します。 +- `-ldflags`フラグを使用してCLIに指定された追加のldflagsを、デフォルトのタグに追記します。 +- `-o`フラグのパラメータをパススルーさせます。 +- `-compiler`フラグで指定されたGoコンパイラを、コンパイル時に使用するようにします。 + +#### 手動で実行する手順 + +- 開発ビルドの場合、最小のコマンドは次のとおりです: `go build -tags dev -gcflags "all=-N -l"` +- 本番ビルドの場合、最小のコマンドは次のとおりです: `go build -tags desktop,production -ldflags "-w -s -H windowsgui"` +- `.syso`ファイルと同じディレクトリでコンパイルするようにしてください。 + +### アプリケーションの圧縮 + +#### Wails CLIでの手順 + +- `-upx`フラグが指定された場合、アプリケーションを圧縮するために、`upx`プログラムをデフォルト設定で実行します。 +- `-upxflags`フラグも指定された場合、デフォルト設定の代わりにこれらのフラグを使用します。 + +#### 手動で実行する手順 + +- `upx [flags]`を手動で実行して、アプリケーションを圧縮します。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx new file mode 100644 index 00000000000..68319030e81 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx @@ -0,0 +1,191 @@ +# v1からの移行 + +## 概要 + +Wails v2は、v1から大幅に変更されています。 このドキュメントでは、変更点、および既存のプロジェクトを移行する方法に焦点をあてて説明します。 + +### アプリケーションの作成 + +v1では、`wails.CreateApp`でメインアプリケーションを作成して、`app.Bind`でバインディングを追加し、`app.Run()`でアプリケーションを起動していました。 + +例: + +```go title="v1" + app := wails.CreateApp(&wails.AppConfig{ + Title: "MyApp", + Width: 1024, + Height: 768, + JS: js, + CSS: css, + Colour: "#131313", + }) + app.Bind(basic) + app.Run() +``` + +v2では、`wails.Run()`メソッドだけが、[アプリケーションオプション](../reference/options.mdx#application-options)を指定することができます。 + +```go title="v2" + err := wails.Run(&options.App{ + Title: "MyApp", + Width: 800, + Height: 600, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + basic, + }, + }) +``` + +### バインディング + +v1では、任意の関数と構造体の両方をバインドすることが可能でした。 v2では、構造体のみバインドできるようになり、シンプルになりました。 v1において`Bind()`メソッドに渡していた構造体のインスタンスは、[アプリケーションオプション](../reference/options.mdx#application-options)の`Bind`フィールドで指定できます。 + +```go title="v1" + app := wails.CreateApp(/* options */) + app.Bind(basic) +``` + +```go title="v2" + err := wails.Run(&options.App{ + /* other options */ + Bind: []interface{}{ + basic, + }, + }) +``` + +v1では、バインドされたメソッドをフロントエンドから利用するには`window.backend`を使用していました。 これは`window.go`に変更されました。 + +### アプリケーションライフサイクル + +v1では、バインドされた構造体の中に、`WailsInit()`および`WailsShutdown()`という2つの特別なメソッドが存在しました。 これらは、[アプリケーションオプション](../reference/options.mdx#application-options)の一部として、3つのライフサイクルフックに置き換えられています: + +- [OnStartup](../reference/options.mdx#onstartup) +- [OnShutdown](../reference/options.mdx#onshutdown) +- [OnDomReady](../reference/options.mdx#ondomready) + +注意: [OnDomReady](../reference/options.mdx#ondomready)は、v1での`wails:ready`システムイベントに代わるものです。 + +これらのメソッドは標準的な関数を指定できますが、一般的には、それらのメソッドを構造体の一部として保持しておきます: + +```go title="v2" + basic := NewBasicApp() + err := wails.Run(&options.App{ + /* Other Options */ + OnStartup: basic.startup, + OnShutdown: basic.shutdown, + OnDomReady: basic.domready, + }) +... +type Basic struct { + ctx context.Context +} +func (b *Basic) startup(ctx context.Context) { + b.ctx = ctx +} +... +``` + +### ランタイム + +v2のランタイムはv1よりも非常に充実しており、メニュー、ウィンドウ操作、優れたダイアログをサポートしています。 メソッドのシグネチャが若干変更されていますので、詳しくは[ランタイムのリファレンス](../reference/runtime/intro.mdx)を参照してください。 + +v1では、`WailsInit()`に渡された構造体を介して[ランタイム](../reference/runtime/intro.mdx)を利用できていました。 v2では、ランタイムは独自のパッケージとして移植されています。 ランタイムの各メソッドは、[OnStartup](../reference/options.mdx#onstartup)メソッドで受け渡される`context.Context`を引数に取ります。 + +```go title="Runtime Example" +package main + +import "github.com/wailsapp/wails/v2/pkg/runtime" + +type Basic struct { + ctx context.Context +} + +// startupはアプリケーション起動時に呼び出される +func (a *App) startup(ctx context.Context) { + a.ctx = ctx + runtime.LogInfo(ctx, "Application Startup called!") +} + +``` + +### アセット + +v2での_最も大きな_変更は、アセットの取り扱い方です。 + +v1では、2つのアプリケーションオプションを介してアセットを指定していました: + +- `JS` - アプリケーションのJavaScript +- `CSS` - アプリケーションのCSS + +これは、単一のJSファイルおよびCSSファイルを、開発者が責任をもって作成する必要があることを意味していました。 基本的には、webpackのような複雑なパッカーを使用する必要がありました。 + +v2では、Wailsは一般的なWebサーバと同じように、フロントエンドアセットは何でも構いません。 すべてのアプリケーションアセットは、`embed.FS`インスタンスとしてアプリケーションオプションに渡されます。 + +**つまりアセットをバンドルしたり、画像をBase64でエンコードしたり、カスタムフォントを使用するためにバンドラーの設定を工夫したりする必要は一切ありません**。 + +アプリケーション起動時に、Wailsは、あらかじめ`embed.FS`で指定されたディレクトリ内をスキャンして`index.html`を探し、Webサーバの挙動のように、その場所をすべてのアプリケーションアセットのルートパスとみなします。 + +例: とあるアプリケーションのプロジェクトディレクトリの構成が次のようになっているとします。 この場合、最終的に必要なすべてのアセットは`frontend/dist`ディレクトリ配下に配置される必要があります: + +```shell +. +├── build/ +├── frontend/ +│ └── dist/ +│ ├── index.html +│ ├── main.js +│ ├── main.css +│ └── logo.svg +├── main.go +└── wails.json +``` + +これらのアセットは、`embed.FS`を定義するだけで、アプリケーションから使用することができます: + +```go title="Assets Example" +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + err := wails.Run(&options.App{ + /* Other Options */ + AssetServer: &assetserver.Options{ + Assets: assets, + }, + }) +} +``` + +もちろん、必要に応じてバンドラを使用することもできます。 唯一行わなければいけないことは、[アプリケーションオプション](../reference/options.mdx#application-options)の`Assets`キーに`embed.FS`インスタンスを指定して、Wailsにアプリケーションアセットディレクトリを教えてあげることです。 + +### プロジェクト構成 + +v1では、プロジェクトルートに存在する`project.json`ファイルで、プロジェクト構成を管理していました。 v2では、プロジェクトルートにある`wails.json`ファイルでプロジェクト構成を管理します。 + +フォーマットは若干変更されています。 比較表は次のとおりです: + +

+ +| v1 | v2 | 備考 | +| ------------------ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | name | | +| description | | 消去されました | +| author / name | author / name | | +| author / email | author / email | | +| version | version | | +| binaryname | outputfilename | 変更されました | +| frontend / dir | | 消去されました | +| frontend / install | frontend:install | 変更されました | +| frontend / build | frontend:build | 変更されました | +| frontend / bridge | | 消去されました | +| frontend / serve | | 消去されました | +| tags | | 消去されました | +| | wailsjsdir | wailsjsモジュールを生成するディレクトリ | +| | assetdir | `dev`モードでコンパイルされたフロントエンドアセットのディレクトリ。 通常は自動推定されるため、空のままで構いません。 | +| | reloaddirs | `dev`モードでリロードをトリガーさせたい追加のディレクトリを指定するための、カンマ区切りのリスト。 高度なアセット構成をとる場合にのみ必要です。 | + +

diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx new file mode 100644 index 00000000000..58ee21c687a --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx @@ -0,0 +1,25 @@ +# マウスボタン + +Wailsランタイムでは、マウスクリックを途中で捕捉し、フレームレスウィンドウのサイズ変更が必要かどうかや、ウィンドウの移動が必要かどうかを判断しています。 `window.onclick`はマウスボタンを正しく報告しないため、どのようにマウスクリックが発生したことを検出しているのかを尋ねられました。 以下のコードは、マウスクリックを検出する方法を示しています: + +```javascript +window.addEventListener("mousedown", handleMouseButtonDown); + +function handleMouseButtonDown(event) { + if (event.button === 0) { + // left mouse button + } else if (event.button === 1) { + // middle mouse button + } else if (event.button === 2) { + // right mouse button + } else if (event.button === 3) { + // back mouse button + } else if (event.button === 4) { + // forward mouse button + } else { + // other mouse button + } +} +``` + +参考: https://developer.mozilla.org/ja/docs/Web/API/MouseEvent/button diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx new file mode 100644 index 00000000000..9b5bab1fe7f --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx @@ -0,0 +1,40 @@ +# 難読化されたビルド + +Wailsでは、[garble](https://github.com/burrowers/garble)を使用したアプリケーションの難読化をサポートしています。 + +`wails build`コマンドで`-obfuscate`フラグを使用することで、ビルド時に難読化を有効にすることができます: + +```bash +wails build -obfuscated +``` + +また、難読化に関する設定をカスタマイズするために、`-garbleargs`フラグを使用できます: + +```bash +wails build -obfuscated -garbleargs "-literals -tiny -seed=myrandomseed" +``` + +これらの設定は、[プロジェクト構成](../reference/project-config)で記述されている場合もあります。 + +## 動作の仕組み + +標準のビルドでは、バインドされたすべてのメソッドは、フロントエンドの`window.go`変数から利用することができます。 これらのメソッドが呼び出されると、対応するバックエンドメソッドが完全修飾関数名で呼び出されます。 難読化ビルドの場合、メソッドは名前の代わりにIDでバインドされます。 `wailsjs`ディレクトリに生成されたバインディングは、このIDを使用してバックエンドの関数を呼び出します。 + +:::note + +アプリケーションを難読化した状態で動作させるためには、`wailsjs`ディレクトリの配下に生成されたバインディングを使用する必要があります。 + +::: + +## 例 + +Importing the "Greet" method from the bindings like this: + +```js +import { Greet } from "../../wailsjs/go/main/App"; + +// snip +Greet("World"); +``` + +これは、バインディングがIDで再生成され、呼び出しメカニズムが更新されるため、難読化モードでメソッドが正しく動作することを保証します。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx new file mode 100644 index 00000000000..4ee1db0e4ff --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx @@ -0,0 +1,10 @@ +# オーバースクロール + +[オーバースクロール](https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior)は、ページコンテンツの境界を越えてスクロールした際に発生する"バウンス効果"です。 この効果はモバイルアプリでよく見かけます。 CSSを使用することでこの効果を無効化できます: + +```css +html { + height: 100%; + overflow: hidden; +} +``` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx new file mode 100644 index 00000000000..ba9195d2bb2 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx @@ -0,0 +1,47 @@ +# ルーティング + +アプリケーションでビューを切り替える一般的な方法は、ルーティングです。 このページでは、ルーティングを実現する方法をいくつか紹介します。 + +## Vue + +Vueにおいてルーティングで推奨されるアプローチは、[ハッシュモード](https://next.router.vuejs.org/guide/essentials/history-mode.html#hash-mode)となります: + +```js +import { createRouter, createWebHashHistory } from "vue-router"; + +const router = createRouter({ + history: createWebHashHistory(), + routes: [ + //... + ], +}); +``` + +## Angular + +Angularにおいてルーティングで推奨されるアプローチは、[HashLocationStrategy](https://codecraft.tv/courses/angular/routing/routing-strategies#_hashlocationstrategy)となります: + +```ts +RouterModule.forRoot(routes, { useHash: true }); +``` + +## React + +Reactにおいてルーティングで推奨されるアプローチは、[HashRouter](https://reactrouter.com/en/main/router-components/hash-router)となります: + +```jsx +import { HashRouter } from "react-router-dom"; + +ReactDOM.render( + + {/* The rest of your app goes here */} + + } exact /> + } /> + } /> + {/* more... */} + + , + root +); +``` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx new file mode 100644 index 00000000000..8b57d7e0fe3 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx @@ -0,0 +1,387 @@ +# コード署名 + +このガイドでは、MacOSおよびWindowsでWailsによって生成されたバイナリに署名するための方法を解説します。 このガイドは、CI環境、とりわけGitHub Actionsを対象としています。 + +## Windows + +まず初めに、コード署名証明書が必要となります。 まだ証明書を持っていない場合は、[こちら](https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/get-a-code-signing-certificate)のMicrosoftのページに、いくつかのプロバイダーが紹介されていますので入手してください、 デバイスドライバといったカーネルレベルのソフトウェアを作成する必要がない限り、EV証明書を入手する必要はありません。 Wailsアプリに署名する場合、標準のコード証明書で問題ありません。 + +自動ビルドシステムを対象に作業する前に、ローカルマシン上でバイナリに署名する方法を証明書プロバイダに確認し、特別な要件がないかを確認することを推奨します。 例えば、[こちら](https://www.ssl.com/how-to/using-your-code-signing-certificate/)はSSL.comのWindows向けコード署名ガイドです。 ローカル環境での署名方法が分かっていれば、CI環境で発生するかもしれない問題のトラブルシューティングが容易になることでしょう。 例えば、SSL.comのコード署名証明書は[SignTool.exe](https://docs.microsoft.com/en-us/windows/win32/seccrypto/signtool)において`/tr`フラグを指定する必要がありますが、他の証明書プロバイダでは、タイムスタンプサーバの提供のために、`/t`フラグのみ必要である場合もあります。 [こちら](https://github.com/Dana-Prajea/code-sign-action)のような、Windowsバイナリの署名によく使われるGitHub Actionsのアクションは、SignTool.exeの`/tr`フラグに対応していません。 したがって、このガイドではPowerShellコマンドを使用して手動でアプリケーションに署名する方法に焦点をあてます。ただし、必要であれば[code-sign-action](https://github.com/Dana-Prajea/code-sign-action)アクションといったアクションを使用することも可能です。 + +まずは、GitHub CIでWailsアプリをビルドできるようにしておきましょう。 簡単なワークフローテンプレートは次のとおりです: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # wails.jsonでフロントエンドのビルドおよびインストールコマンドを設定していない場合、ここで手動でフロントエンドをビルドする必要があるかもしれません。 + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +次に、GitHubワークフローに署名証明書へのアクセス権を付与する必要があります。 これは、.pfxまたは.p12形式の証明書をbase64文字列にエンコードすることで実現できます。 PowerShellの場合、証明書名が仮に'my-cert.p12'だとすると、次のコマンドが使用できます: + +```PowerShell +certutil -encode .\my-cert.p12 my-cert-base64.txt +``` + +これで、base64でエンコードされた証明書が含まれる.txtファイルが作成されます。 このファイルの中身は、_-----BEGIN CERTIFICATE-----_で始まり、_-----END CERTIFICATE-----_で終わる必要があります。 次に、GitHubで2つのActions secretsを作成します。 _Settings -> Secrets -> Actions_のページに移動し、2つのシークレットを作成してください: + +- **WIN_SIGNING_CERT** には、base64エンコードされた証明書テキストの内容を設定します。 +- **WIN_SIGNING_CERT_PASSWORD** には、証明書のパスワードを設定します。 + +ここまでの作業で、次の2つのいずれかの方法を使用して、ワークフローによる署名処理を実装する準備が整いました。 + +### 方法1: コマンドを使用して署名 + +この方法では、Power Shellコマンドを使用してアプリに署名し、署名プロセス全体をコントロールします。 + +`"Build Wails app"`ステップのあとに、下記のステップをワークフローに追加してください。 + +```yaml +- name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd /t /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' + +``` + +このスクリプトでは、証明書ファイル用に新しいディレクトリを作成して、base64シークレットから証明書ファイルを作成します。その証明書を.pfxファイルに変換し、最後にバイナリへ署名します。 下記の変数は、最後の行内で置換してください: + +- **signing algorithm**: 通常は、sha256。 +- **timestamping server**: 証明書で使用するタイムスタンプサーバのURL。 +- **path to binary**: 署名したいバイナリへのパス。 + +Wailsの構成において`outputfilename`に"app.exe"という値が設定されており、SSL.comでの証明書が用意されている場合、次のようなワークフローとなります: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # wails.jsonでフロントエンドのビルドおよびインストールコマンドを設定していない場合、ここで手動でフロントエンドをビルドする必要があるかもしれません。 + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\app.exe + + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +### 方法2: アクションを使用して自動的に署名 + +[こちら](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate)のようなWindowsコード署名のためのアクションを使用することはできますが、証明書用のSHA1ハッシュや証明書名が必要であることに注意してください。 詳しくは、アクションの[マーケットプレイス](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate)で、使用方法を確認してください。 + +--- + +## MacOS + +まずは、Appleのコード署名証明書が必要です。 もし所有していない場合は、Googleで検索すれば取得方法が分るでしょう。 証明書を入手できたら、それをエクスポートし、base64でエンコードする必要があります。 [このチュートリアル](https://localazy.com/blog/how-to-automatically-sign-macos-apps-using-github-actions)をご覧いただければ、簡単にエンコードする方法が分ります。 .p12証明書ファイルをエクスポートした場合、次のコマンドを使用して、チュートリアルで示されているようにbase64にエンコードできます: + +```bash +base64 Certificates.p12 | pbcopy +``` + +これにより、Windowsと同様に、GitHubプロジェクトにいくつかのシークレットを設定する準備が整いました: + +- **APPLE_DEVELOPER_CERTIFICATE_P12_BASE64**には、新しくコピーしたbase64証明書の内容を設定します。 +- **APPLE_DEVELOPER_CERTIFICATE_PASSWORD**には、証明書のパスワードを設定します。 +- **APPLE_PASSWORD**には、[こちら](https://appleid.apple.com/account/manage)で生成できるアプリ固有のパスワードを設定します。 + +GitHub Actionのワークフローで、Wailsアプリをビルドできるようにしましょう。 簡単な例は次のとおりです: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # wails.jsonでフロントエンドのビルドおよびインストールコマンドを設定していない場合、ここで手動でフロントエンドをビルドする必要があるかもしれません。 + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +macOSでコード署名をするときは、[gon](https://github.com/mitchellh/gon)という非常に便利なツールを使うことで、コード署名およびAppleサーバとの通信ができます。これはGoで記述されており、このガイドでも使用されています。 + +`Build Wails app`ステップの後に、次のワークフローを追加します: + +```yaml +- name: MacOS download gon for code signing and app notarization + if: matrix.platform == 'macos-latest' + run: | + brew install mitchellh/gon/gon +``` + +ここで、`build/darwin`ディレクトリ内に、gonの構成設定ファイルを用意する必要があります: + +1. gon-sign.json: + +```json +{ + "source": ["./build/bin/app.app"], + "bundle_id": "app.myapp", + "apple_id": { + "username": "my-appleid@email.com", + "password": "@env:APPLE_PASSWORD" + }, + "sign": { + "application_identity": "Developer ID Application: My Name" + } +} +``` + +`source`にはWailsのバイナリファイルの場所、`bundle_id`にはバンドルID、`apple_id`にはあらかじめ作成したApple IDのユーザ名とアプリ固有のパスワード、`sign.application_identity`には次のコマンドを実行することで分かるIDを指定します: + +```bash +security find-identity -v -p codesigning +``` + +2. entitlements.plist: + +```plist + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + + +``` + +このファイルでは、アプリに必要な権限(たとえば、アプリがカメラを使用する場合、カメラへのアクセス権限)を設定します。 権限について詳しくは[こちら](https://developer.apple.com/documentation/bundleresources/entitlements)をご覧ください。 + +`Info.plist`ファイルのバンドルIDを、`gon-sign.json`に入力したものと同じIDに書き換えてください。 次は、`Info.plist`ファイルの例です: + +```plist + + + CFBundlePackageTypeAPPL + CFBundleNameMyApp + CFBundleExecutableapp + CFBundleIdentifierapp.myapp + CFBundleVersion0.1.0 + CFBundleGetInfoStringMy app is cool and nice and chill and + CFBundleShortVersionString0.1.0 + CFBundleIconFileiconfile + LSMinimumSystemVersion10.13.0 + NSHighResolutionCapabletrue + LSApplicationCategoryTypepublic.app-category.utilities + NSHumanReadableCopyright© Me + +``` + +これで、Wailsアプリをビルドしたあとに、ワークフローに署名のステップを追加する準備ができました: + +```yaml +- name: Import Code-Signing Certificates for macOS + if: matrix.platform == 'macos-latest' + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} +- name: Sign our macOS binary + if: matrix.platform == 'macos-latest' + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json +``` + +Appleでバイナリに署名する場合、数分から数時間程度の所要時間がかかることがありますのでご注意ください。 + +## ワークフローファイルの組み合わせ + +WindowsとmacOSを組み合わせたGitHubワークフローファイルの例は次のとおりです: + +```yaml +name: "example combined" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # wails.jsonでフロントエンドのビルドおよびインストールコマンドを設定していない場合、ここで手動でフロントエンドをビルドする必要があるかもしれません。 + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: MacOS download gon for code signing and app notarization + if: matrix.platform == 'macos-latest' + run: | + brew install mitchellh/gon/gon + - name: Import Code-Signing Certificates for macOS + if: matrix.platform == 'macos-latest' + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} + - name: Sign our macOS binary + if: matrix.platform == 'macos-latest' + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json + - name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\Monitor.exe + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +# おわりに + +このガイドは、RiftShareプロジェクトとそのワークフローに触発されて作成されたものであり、 [こちら](https://github.com/achhabra2/riftshare/blob/main/.github/workflows/build.yaml)を併せて確認することを強く推奨します。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx new file mode 100644 index 00000000000..dc7706f8ffa --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx @@ -0,0 +1,81 @@ +# Single Instance Lock + +Single instance lock is a mechanism that allows you to prevent multiple instances of your app from running at the same time. +It is useful for apps that are designed to open files from the command line or from the OS file explorer. + +## Important + +Single Instance Lock does not implement a secure communications protocol between instances. When using single instance lock, +your app should treat any data passed to it from second instance callback as untrusted. +You should verify that args that you receive are valid and don't contain any malicious data. + +## How it works + +Windows: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via a shared window using [SendMessage](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage) +macOS: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via [NSDistributedNotificationCenter](https://developer.apple.com/documentation/foundation/nsdistributednotificationcenter) +Linux: Single instance lock is implemented using [dbus](https://www.freedesktop.org/wiki/Software/dbus/). The dbus name is generated from the unique id that you provide. Data is passed to the first instance via [dbus](https://www.freedesktop.org/wiki/Software/dbus/) + +## Usage + +When creating your app, you can enable single instance lock by passing a `SingleInstanceLock` struct to the `App` struct. +Use the `UniqueId` field to specify a unique id for your app. +This id is used to generate the mutex name on Windows and macOS and the dbus name on Linux. Use a UUID to ensure that the id is unique. +The `OnSecondInstanceLaunch` field is used to specify a callback that is called when a second instance of your app is launched. +The callback receives a `SecondInstanceData` struct that contains the command line arguments passed to the second instance and the working directory of the second instance. + +Note that OnSecondInstanceLaunch don't trigger windows focus. +You need to call `runtime.WindowUnminimise` and `runtime.Show` to bring your app to the front. +Note that on linux systems window managers may prevent your app from being brought to the front to avoid stealing focus. + +```go title="main.go" +var wailsContext *context.Context + +// NewApp creates a new App application struct +func NewApp() *App { + return &App{} +} + +// startup is called when the app starts. The context is saved +// so we can call the runtime methods +func (a *App) startup(ctx context.Context) { + wailsContext = &ctx +} + +func (a *App) onSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) { + secondInstanceArgs = secondInstanceData.Args + + println("user opened second instance", strings.Join(secondInstanceData.Args, ",")) + println("user opened second from", secondInstanceData.WorkingDirectory) + runtime.WindowUnminimise(*wailsContext) + runtime.Show(*wailsContext) + go runtime.EventsEmit(*wailsContext, "launchArgs", secondInstanceArgs) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + OnStartup: app.startup, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx new file mode 100644 index 00000000000..4651c422ed1 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx @@ -0,0 +1,153 @@ +# SvelteKit + +This guide will go into: + +1. Miminal Installation Steps - The steps needed to get a minimum Wails setup working for SvelteKit. +2. Install Script - Bash script for accomplishing the Minimal Installation Steps with optional Wails branding. +3. Important Notes - Issues that can be encountered when using SvelteKit + Wails and fixes. + +## 1. Minimal Installation Steps + +##### Install Wails for Svelte. + +- `wails init -n myapp -t svelte` + +##### Delete the svelte frontend. + +- Navigate into your newly created myapp folder. +- Delete the folder named "frontend" + +##### While in the Wails project root. Use your favorite package manager and install SvelteKit as the new frontend. Follow the prompts. + +- `npm create svelte@latest frontend` + +##### Modify wails.json. + +- Add `"wailsjsdir": "./frontend/src/lib",` Do note that this is where your Go and runtime functions will appear. +- Change your package manager frontend here if not using npm. + +##### Modify main.go. + +- The first comment `//go:embed all:frontend/dist` needs to be changed to `//go:embed all:frontend/build` + +##### Install/remove dependencies using your favorite package manager. + +- Navigate into your "frontend" folder. +- `npm i` +- `npm uninstall @sveltejs/adapter-auto` +- `npm i -D @sveltejs/adapter-static` + +##### Change adapter in svelte.config.js + +- First line of file change `import adapter from '@sveltejs/adapter-auto';` to `import adapter from '@sveltejs/adapter-static';` + +##### Put SvelteKit into SPA mode with prerendering. + +- Create a file under myapp/frontend/src/routes/ named +layout.ts/+layout.js. +- Add two lines into the newly created file `export const prerender = true` and `export const ssr = false` + +##### Test installation. + +- Navigate back into the Wails project root (one directory up). +- run `wails dev` +- If the application doesn't run please check through the previous steps. + +## 2. Install Script + +##### This Bash Script does the steps listed above. Make sure to read over the script and understand what the script is doing on your computer. + +- Create a file sveltekit-wails.sh +- Copy the below code into the new file then save it. +- Make it executable with `chmod +x sveltekit-wails.sh` +- Brand is an optional param below that adds back in the wails branding. Leave third param blank to not insert the Wails branding. +- Example usage: `./sveltekit-wails.sh pnpm newapp brand` + +##### sveltekit-wails.sh: + +``` +manager=$1 +project=$2 +brand=$3 +wails init -n $project -t svelte +cd $project +sed -i "s|npm|$manager|g" wails.json +sed -i 's|"auto",|"auto",\n "wailsjsdir": "./frontend/src/lib",|' wails.json +sed -i "s|all:frontend/dist|all:frontend/build|" main.go +if [[ -n $brand ]]; then + mv frontend/src/App.svelte +page.svelte + sed -i "s|'./assets|'\$lib/assets|" +page.svelte + sed -i "s|'../wails|'\$lib/wails|" +page.svelte + mv frontend/src/assets . +fi +rm -r frontend +$manager create svelte@latest frontend +if [[ -n $brand ]]; then + mv +page.svelte frontend/src/routes/+page.svelte + mkdir frontend/src/lib + mv assets frontend/src/lib/ +fi +cd frontend +$manager i +$manager uninstall @sveltejs/adapter-auto +$manager i -D @sveltejs/adapter-static +echo -e "export const prerender = true\nexport const ssr = false" > src/routes/+layout.ts +sed -i "s|-auto';|-static';|" svelte.config.js +cd .. +wails dev +``` + +## 3. Important Notes + +##### Server files will cause build failures. + +- \+layout.server.ts, +page.server.ts, +server.ts or any file with "server" in the name will fail to build as all routes are prerendered. + +##### The Wails runtime unloads with full page navigations! + +- Anything that causes full page navigations: `window.location.href = '//'` or Context menu reload when using wails dev. What this means is that you can end up losing the ability to call any runtime breaking the app. There are two ways to work around this. +- Use `import { goto } from '$app/navigation'` then call `goto('//')` in your +page.svelte. This will prevent a full page navigation. +- If full page navigation can't be prevented the Wails runtime can be added to all pages by adding the below into the `` of myapp/frontend/src/app.html + +``` + +... + + + +... + +``` + +See https://wails.io/docs/guides/frontend for more information. + +##### Inital data can be loaded and refreshed from +page.ts/+page.js to +page.svelte. + +- \+page.ts/+page.js works well with load() https://kit.svelte.dev/docs/load#page-data +- invalidateAll() in +page.svelte will call load() from +page.ts/+page.js https://kit.svelte.dev/docs/load#rerunning-load-functions-manual-invalidation. + +##### Error Handling + +- Expected errors using Throw error works in +page.ts/+page.js with a +error.svelte page. https://kit.svelte.dev/docs/errors#expected-errors +- Unexpected errors will cause the application to become unusable. Only recovery option (known so far) from unexpected errors is to reload the app. To do this create a file myapp/frontend/src/hooks.client.ts then add the below code to the file. + +``` +import { WindowReloadApp } from '$lib/wailsjs/runtime/runtime' +export async function handleError() { + WindowReloadApp() +} +``` + +##### Using Forms and handling functions + +- The simplest way is to call a function from the form is the standard, bind:value your variables and prevent submission `` +- The more advanced way is to use:enhance (progressive enhancement) which will allow for convenient access to formData, formElement, submitter. The important note is to always cancel() the form which prevents server side behavior. https://kit.svelte.dev/docs/form-actions#progressive-enhancement Example: + +``` + { + cancel() + console.log(Object.fromEntries(formData)) + console.log(formElement) + console.log(submitter) + handle() +}}> +``` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx new file mode 100644 index 00000000000..8e1f8304557 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx @@ -0,0 +1,97 @@ +# テンプレート + +Wailsは、事前に作成されたテンプレートからプロジェクトを生成します。 v1では、テンプレートがメンテナンス困難なプロジェクトとなり、時代遅れとなってしまう可能性がありました。 v2では、コミュニティを強化するために、テンプレートにいくつかの新機能が追加されました: + +- [リモート点テンプレート](../reference/cli.mdx#remote-templates)からプロジェクトを生成する機能 +- 独自のテンプレートの作成に役立つツール + +## テンプレートの作成 + +テンプレートを作成するには、`wails generate template`コマンドを使用します。 デフォルトのテンプレートを生成する場合は、次のコマンドを実行してください: + +`wails generate template -name mytemplate` + +これにより、デフォルトのファイルが含まれた"mytemplate"ディレクトリが作成されます: + +```shell title=mytemplate/ +. +|-- NEXTSTEPS.md +|-- README.md +|-- app.tmpl.go +|-- frontend +| `-- dist +| |-- assets +| | |-- fonts +| | | |-- OFL.txt +| | | `-- nunito-v16-latin-regular.woff2 +| | `-- images +| | `-- logo-dark.svg +| |-- index.html +| |-- main.css +| `-- main.js +|-- go.mod.tmpl +|-- main.tmpl.go +|-- template.json +`-- wails.tmpl.json +``` + +### テンプレートの概要 + +デフォルトのテンプレートは、次のファイルおよびディレクトリで構成されています: + +| ファイル名 / ディレクトリ名 | 説明 | +| --------------- | ----------------------- | +| NEXTSTEPS.md | テンプレートを完成させる手順を記した説明 | +| README.md | テンプレートとともに公開されるREADME | +| app.tmpl.go | `app.go`のテンプレートファイル | +| frontend/ | フロントエンドアセットを含むディレクトリ | +| go.mod.tmpl | `go.mod`のテンプレートファイル | +| main.tmpl.go | `main.go`のテンプレートファイル | +| template.json | テンプレートのメタデータ | +| wails.tmpl.json | `wails.json`のテンプレートファイル | + +このあとは、`NEXTSTEPS.md`に記述されている手順に従うことを推奨します。 + +## 既存プロジェクトからのテンプレート作成 + +テンプレートの生成時にプロジェクトへのパスを渡すことで、既存のフロントエンドプロジェクトから、テンプレートを作成することができます。 ここでは、Vue3テンプレートの作成方法を説明します: + +- Vue Cliをインストールする: `npm install -g @vue/cli` +- デフォルトのプロジェクトを作成する: `vue create vue3-base` + - その際、`Default (Vue 3) ([Vue 3] babel, eslint)`を選択します +- プロジェクトが作成されたあとに、次のコマンドを実行する: + +```shell +> wails generate template -name wails-vue3-template -frontend .\vue3-base\ +Extracting base template files... +Migrating existing project files to frontend directory... +Updating package.json data... +Renaming package.json -> package.tmpl.json... +Updating package-lock.json data... +Renaming package-lock.json -> package-lock.tmpl.json... +``` + +- `NEXTSTEPS.md`ファイルに記述されているように、テンプレートをカスタマイズする +- ファイルの準備ができたら、次のコマンドを実行してテストする: `wails init -n my-vue3-project -t .\wails-vue3-template\` +- 新しいプロジェクトの動作をテストするために、次のコマンドを実行する: `cd my-vue3-project`および`wails build` +- プロジェクトがコンパイルされたら、実行する: `.\build\bin\my-vue3-project.exe` +- Vue3アプリケーションが完全に動作していることを確認する + +```mdx-code-block +
+ +
+``` + +## テンプレートの公開 + +テンプレートを公開するためにすることは、ファイルをGitHubにプッシュすることだけです。 以下のベストプラクティスを実施することを推奨します: + +- 不要なファイルやディレクトリ(`.git`など)をフロントエンドディレクトリから削除する +- `template.json`がきちんと記述されていること、とくに`helpurl`が記述されていることを確認する +- ファイルをGitHubにプッシュする +- [コミュニティのテンプレート](../community/templates.mdx)ページにプルリクエストを作成する +- [Template Announcement](https://github.com/wailsapp/wails/discussions/825)のディスカッションボードでテンプレートをアナウンスする diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx new file mode 100644 index 00000000000..eb93618657c --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx @@ -0,0 +1,368 @@ +# トラブルシューティング + +このページは、トラブルシューティングを手助けするヒント集です。 + +## `wails`コマンドが見つからないのですが? + +`wails`コマンドが見つからないとシステムに怒られた場合は、Goが、公式のGoインストール手順に従って導入されているかを確認してください。 コマンドが見つからないほとんどの理由は、あなたのホームディレクトリ配下にある`go/bin`ディレクトリのパスが、`PATH`環境変数に含まれていないからです。 また、インストールによって行われた環境変更を反映させるために、もともと開いていたコマンドプロンプト(ターミナル)がある場合はそれらをいったん閉じて、再度開きなおしてください。 + +## アプリケーションがホワイト/ブラックスクリーン表示になってしまいます + +アプリケーション内で、正しいディレクトリでアセットが指定されていることを確認してください。 `main.go`ファイル内には、以下のようなコードが存在します: + +```go +//go:embed all:frontend/dist +var assets embed.FS +``` + +また、`frontend/dist`ディレクトリ内に、アプリケーションアセットがきちんと含まれているか確認してください。 + +### Mac + +この事象がMacで発生した場合は、`Info.plist`に以下の記述を追加してみてください: + +```xml +NSAppTransportSecurity + + NSAllowsLocalNetworking + + +``` + +参考: https://github.com/wailsapp/wails/issues/1504#issuecomment-1174317433 + +## Macのアプリケーションが無効になっています + +ビルドしたアプリケーションが次のように表示される場合: + +```mdx-code-block +

+ +

+``` + +アプリケーションの`info.plist`が無効である可能性があります。 `build/.app/Contents/info.plist`ファイルを更新し、データが有効かどうかを確認します。たとえば、バイナリ名が正しいかどうかを確認してください。 変更を反映するには、ファイルを`build/darwin`ディレクトリにコピーします。 + +## Windowsのエクスプローラにアプリケーションアイコンが正しく表示されません + +アプリケーションアイコンが正しく表示されない場合は、`C:\Users\<あなたのユーザ名>\AppData\Local`ディレクトリ内にある、`IconCache.db`という隠しファイルを削除してみてください。 これにより、Windowsのアイコンキャッシュが強制的に再作成されます。 + +出典: https://github.com/wailsapp/wails/issues/2360#issuecomment-1556070036 + +## 可変長引数を持つバックエンドメソッドをフロントエンドから呼び出せません + +次のように、可変長引数を持つバックエンドメソッドが定義されている場合: + +```go +func (a *App) TestFunc(msg string, args ...interface{}) error { + // Code +} +``` + +このメソッドを、次のようにフロントエンドから呼び出すと失敗します: + +```js +var msg = "Hello: "; +var args = ["Go", "JS"]; +window.go.main.App.TestFunc(msg, ...args) + .then((result) => { + //do things here + }) + .catch((error) => { + //handle error + }); +``` + +回避方法: + +```js +var msg = "Hello "; +var args = ["Go", "JS"]; +window.go.main.App.TestFunc(msg, args) + .then((result) => { + //without the 3 dots + //do things here + }) + .catch((error) => { + //handle error + }); +``` + +出典: https://github.com/wailsapp/wails/issues/1186 + +## Wailsのインストール時にプロキシエラーが発生します + +次のようなエラーが発生する場合: + +``` +"https://proxy.golang.org/github.com/wailsapp/wails/cmd/wails/@v/list": dial tcp 172.217.163.49:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. +``` + +おそらく、公式のGo Proxyがブロックされています (中国のユーザより報告されています)。 解決するには、次のように、プロキシを手動で設定します: + +``` +go env -w GO111MODULE=on +go env -w GOPROXY=https://goproxy.cn,direct +``` + +出典: https://github.com/wailsapp/wails/issues/1233 + +## 生成されたTypeScriptの型定義が正しくありません + +場合によっては、生成されるTypeScriptの型定義が誤っていることがあります。 この事象を軽減させるために、`ts_type`という構造体のタグを使用して、生成する型を指定することができます。 詳しくは、[こちら](https://github.com/tkrajina/typescriptify-golang-structs#custom-types)をご覧ください。 + +## `index.html`から移動するとフロントエンド上でメソッドを呼び出すことができません + +`index.html`から新しいhtmlファイルへ遷移すると、コンテキスト情報は失われてしまいます。 この事象を修正するには、遷移先の新しいページの``セクションに、次のインポートコードを追加します: + +```html + + + + +``` + +出典: https://github.com/wailsapp/wails/discussions/1512 + +## Macで`wails dev`を実行すると`too many open files`エラーが発生します + +デフォルトでは、macOSは最大で256個のファイルしか開くことができません。 この制限により、`wails dev`コマンド実行時に影響が発生する場合があります。 この制限は、ターミナルで次のようなコマンドを実行することで、緩和することができます: `ulimit -n 1024`。 + +FSNotifyは、Macのために、[Appleのfseventsへの移行を検討しています](https://github.com/fsnotify/fsnotify/issues/11)。 この移行が完了しない間は、[こちら](https://github.com/wailsapp/wails/issues/1733)で言及されているように、独自で実装を行います。 + +## Macアプリで不可解なコンパイルエラーが発生します + +一部のユーザより、次のようなコンパイルエラーが発生することがあるという報告を受けています: + +```shell +# github.com/wailsapp/wails/v2/internal/frontend/desktop/darwin +In file included from ../../pkg/mod/github.com/wailsapp/wails/v2@v2.0.0-beta.44.2/internal/frontend/desktop/darwin/callbacks.go:9: +In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:12: +/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSBundle.h:91:143: error: function does not return NSString +- (NSAttributedString *)localizedAttributedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName NS_FORMAT_ARGUMENT(1) NS_REFINED_FOR_SWIFT API_AVAILABLE(macos(12.0), ios(15.0), watchos(8.0), tvos(15.0)); + ~~~~~~~~~~~~~~ ^ ~ +/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:103:48: note: expanded from macro 'NS_FORMAT_ARGUMENT' + #define NS_FORMAT_ARGUMENT(A) __attribute__ ((format_arg(A))) +``` + +これは_一般的に_、実行されているOSのバージョンと、インストールされているXCodeコマンドラインツールのバージョンが不一致であることが原因です。 このようなエラーが発生した場合は、XCodeコマンドラインツールを最新バージョンに更新してみてください。 + +XCodeコマンドラインツールの再インストールが引き続き失敗する場合は、次のコマンドを使用して、ツールキットがどこに配置されているかを確認できます: + +`xcode-select -p` + +`/Applications/Xcode.app/Contents/Developer`と表示された場合、`sudo xcode-select --switch /Library/Developer/CommandLineTools`というコマンドを実行してください。 + +出典: https://github.com/wailsapp/wails/issues/1806 および https://github.com/wailsapp/wails/issues/1140#issuecomment-1290446496 + +## My application won't compile on Mac + +次のようなエラーが発生する場合: + +```shell +l1@m2 GoEasyDesigner % go build -tags dev -gcflags "all=-N -l" +/Users/l1/sdk/go1.20.5/pkg/tool/darwin_arm64/link: running clang failed: exit status 1 +Undefined symbols for architecture arm64: + "_OBJC_CLASS_$_UTType", referenced from: + objc-class-ref in 000016.o +ld: symbol(s) not found for architecture arm64 +clang: error: linker command failed with exit code 1 (use -v to see invocation) +``` +Ensure you have the latest SDK installed. If so and you're still experiencing this issue, try the following: + +```shell +export CGO_LDFLAGS="-framework UniformTypeIdentifiers" && go build -tags dev -gcflags "all=-N -l" +``` + +Sources: https://github.com/wailsapp/wails/pull/2925#issuecomment-1726828562 + + +-- + +## Cannot start service: Host version "x.x.x does not match binary version "x.x.x" + +`frontend/node_modules`と`frontend/package-lock.json`を`.gitignore`に追加することをお勧めします。 そうしないと、異なるバージョンのNodeがインストールされている別のマシンでリポジトリを開いた際に、アプリケーションが実行できなくなる場合があります。 + +この事象が発生した場合は、単純に`frontend/node_modules`と`frontend/package-lock.json`を削除し、`wails build`コマンドおよび`wails dev`コマンドを再実行してください。 + +## ビルドプロセスが"Generating bindings"で停止します + +バインディングの生成プロセスは、アプリケーションを特別なモードで実行します。 アプリケーションに、意図に有無にかかわらず無限ループ(`wails.Run()`のあとに終了されないコード)が含まれている場合、バインディングの生成の段階でビルドプロセスが停止する可能性があります。 コードが正しく終了していることを確認してください。 + +## Mac application flashes white at startup + +This is due to the default background of the webview being white. If you want to use the window background colour instead, you can make the webview background transparent using the following config: + +```go + err := wails.Run(&options.App{ + Title: "macflash", + Width: 1024, + Height: 768, + // Other settings + Mac: &mac.Options{ + WebviewIsTransparent: true, + }, + }) +``` + +## I get a "Microsoft Edge can't read or write to its data directory" error when running my program as admin on Windows + +You set your program to require admin permissions and it worked great! Unfortunately, some users are seeing a "Microsoft Edge can't read or write to its data directory" error when running it. + +When a Windows machine has two local accounts: + +- Alice, an admin +- Bob, a regular user + +Bob sees a UAC prompt when running your program. Bob enters Alice's admin credentials into this prompt. The app launches with admin permissions under Alice's account. + +Wails instructs WebView2 to store user data at the specified `WebviewUserDataPath`. It defaults to `%APPDATA%\[BinaryName.exe]`. + +Because the application is running under Alice's account, `%APPDATA%\[BinaryName.exe]` resolves to `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`. + +WebView2 [creates some child processes under Bob's logged-in account instead of Alice's admin account](https://github.com/MicrosoftEdge/WebView2Feedback/issues/932#issue-807464179). Since Bob cannot access `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`, the "Microsoft Edge can't read or write to its data directory" error is shown. + +Possible solution #1: + +Refactor your application to work without constant admin permissions. If you just need to perform a small set of admin tasks (such as running an updater), you can run your application with the minimum permissions and then use the `runas` command to run these tasks with admin permissions as needed: + +```go +//go:build windows + +package sample + +import ( + "golang.org/x/sys/windows" + "syscall" +) + +// Calling RunAs("C:\path\to\my\updater.exe") shows Bob a UAC prompt. Bob enters Alice's admin credentials. The updater launches with admin permissions under Alice's account. +func RunAs(path string) error { + verbPtr, _ := syscall.UTF16PtrFromString("runas") + exePtr, _ := syscall.UTF16PtrFromString(path) + cwdPtr, _ := syscall.UTF16PtrFromString("") + argPtr, _ := syscall.UTF16PtrFromString("") + + var showCmd int32 = 1 //SW_NORMAL + + err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd) + if err != nil { + return err + } + return nil +} +``` + +Possible solution #2: + +Run your application with extended permissions. If you absolutely must run with constant admin permissions, WebView2 will function correctly if you use a data directory accessible by both users and you also launch your app with the `SeBackupPrivilege`, `SeDebugPrivilege`, and `SeRestorePrivilege` permissions. Here's an example: + +```go +package main + +import ( + "embed" + "os" + "runtime" + + "github.com/fourcorelabs/wintoken" + "github.com/hectane/go-acl" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +//go:embed all:frontend/dist +var assets embed.FS + +const ( + fixedTokenKey = "SAMPLE_RANDOM_KEY" + fixedTokenVal = "with-fixed-token" + webviewDir = "C:\\ProgramData\\Sample" +) + +func runWithFixedToken() { + println("Re-launching self") + token, err := wintoken.OpenProcessToken(0, wintoken.TokenPrimary) //pass 0 for own process + if err != nil { + panic(err) + } + defer token.Close() + + token.EnableTokenPrivileges([]string{ + "SeBackupPrivilege", + "SeDebugPrivilege", + "SeRestorePrivilege", + }) + + cmd := exec.Command(os.Args[0]) + cmd.Args = os.Args + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", fixedTokenKey, fixedTokenVal)) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.SysProcAttr = &syscall.SysProcAttr{Token: syscall.Token(token.Token())} + if err := cmd.Run(); err != nil { + println("Error after launching self:", err) + os.Exit(1) + } + println("Clean self launch :)") + os.Exit(0) +} + +func main() { + if runtime.GOOS == "windows" && os.Getenv(fixedTokenKey) != fixedTokenVal { + runWithFixedToken() + } + + println("Setting data dir to", webviewDir) + if err := os.MkdirAll(webviewDir, os.ModePerm); err != nil { + println("Failed creating dir:", err) + } + if err := acl.Chmod(webviewDir, 0777); err != nil { + println("Failed setting ACL on dir:", err) + } + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "sample-data-dir", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + Windows: &windows.Options{ + WebviewUserDataPath: webviewDir, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +If you use a data directory accessible by both users but not the extended privileges, you will receive a WebView2 `80010108 The object invoked has disconnected from its clients` error. + +Possible future solution #3: [run WebView2 using an in-memory mode if implemented](https://github.com/MicrosoftEdge/WebView2Feedback/issues/3637#issuecomment-1728300982). + +## WebView2 installation succeeded, but the wails doctor command shows that it is not installed + +If you have installed WebView2, but the `wails doctor` command shows that it is not installed, it is likely that the WebView2 runtime installed was for a different architecture. You can download the correct runtime from [here](https://developer.microsoft.com/en-us/microsoft-edge/webview2/). + +Source: https://github.com/wailsapp/wails/issues/2917 + +## WebVie2wProcess failed with kind + +If your Windows app generates this kind of error, you can check out what the error means [here](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2processfailedkind?view=webview2-winrt-1.0.2045.28). + diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx new file mode 100644 index 00000000000..86b7c16a487 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx @@ -0,0 +1,82 @@ + +# Visual Studio Code + +このページでは、Wailsでの開発でVisual Studio Codeを使用する際のさまざまなヒントやコツをご紹介します。 + +## Veturの構成設定 + +このヒントを提供してくれた[@Lyimmi](https://github.com/Lyimmi)に感謝します。 このヒントは[こちら](https://github.com/wailsapp/wails/issues/1791#issuecomment-1228158349)に投稿されたものです。 + +Veturは、Vueプロジェクトのシンタックスハイライトおよびコード補完を提供してくれる、Visual Studio Codeでのポピュラーな拡張機能です。 VSCodeでWailsのプロジェクトを読み込むと、Veturはルートディレクトリでフロントエンドのプロジェクトを見つけようとするため、エラーが発生します。 これを解消するためには、次の手順を実施します: + +プロジェクトのルートディレクトリに、`vetur.config.js`という名前のファイルを作成します。 + +```javascript +// vetur.config.js +/** @type {import('vls').VeturConfig} */ +module.exports = { + // **optional** default: `{}` + // override vscode settings + // Notice: It only affects the settings used by Vetur. + settings: { + "vetur.useWorkspaceDependencies": true, + "vetur.experimental.templateInterpolationService": true + }, + // **optional** default: `[{ root: './' }]` + // support monorepos + projects: [ + { + // **required** + // Where is your project? + // It is relative to `vetur.config.js`. + // root: './packages/repo1', + root: './frontend', + // **optional** default: `'package.json'` + // Where is `package.json` in the project? + // We use it to determine the version of vue. + // It is relative to root property. + package: './package.json', + // **optional** + // Where is TypeScript config file in the project? + // It is relative to root property. + tsconfig: './tsconfig.json', + // **optional** default: `'./.vscode/vetur/snippets'` + // Where is vetur custom snippets folders? + snippetFolder: './.vscode/vetur/snippets', + // **optional** default: `[]` + // Register globally Vue component glob. + // If you set it, you can get completion by that components. + // It is relative to root property. + // Notice: It won't actually do it. You need to use `require.context` or `Vue.component` + globalComponents: [ + './src/components/**/*.vue' + ] + } + ] +} +``` + +次に、`frontend/tsconfig.json`の構成を修正します: + +```javascript +{ + "compilerOptions": { + "module": "system", + "noImplicitAny": true, + "removeComments": true, + "preserveConstEnums": true, + "sourceMap": true, + "outFile": "../../built/local/tsc.js", + "allowJs": true + }, + "exclude": [ + "node_modules", + "**/*.spec.ts" + ], + "include": [ + "src/**/*", + "wailsjs/**/*.ts" + ] +} +``` +以上により、Veturを期待どおりに使用できるようになります。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx new file mode 100644 index 00000000000..3e3ae9b5e70 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx @@ -0,0 +1,58 @@ +# NSISインストーラ + +```mdx-code-block +

+ +
+

+``` + +Wailsでは、[NSISインストーラ](https://nsis.sourceforge.io/)を使用したWindowsインストーラの生成をサポートしています。 + +## NSISのインストール + +### Windows + +インストーラは、[NSISダウンロード](https://nsis.sourceforge.io/Download)ページから入手できます。 + +Chocolateyパッケージマネージャを使用している場合は、次のスクリプトを実行することでインストールできます: + +``` +choco install nsis +``` + +NSISを手動でインストールする場合、NSISインストール時に作成される`makensis.exe`ファイルが含まれた_Bin_フォルダを、パスに追加する必要があります。 Windows上でパスを追加する方法については、[こちら](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/)の優れたチュートリアルをご覧ください。 + +### Linux + +`nsis`パッケージは、ディストリビューションのパッケージマネージャから入手できます。 + +### MacOS + +NSISは、homebrew経由でインストールできます: `brew install nsis`。 + +## インストーラの生成 + +新しくプロジェクトが作成されると、Wailsは、`build/windows/installer`内に、NSIS構成ファイルを生成します。 構成データは`installer/info.json`から読み込まれますが、当該データはプロジェクトの`wails.json`のInfo§の情報を使用するように設定されています: + +```json +// ... + "Info": { + "companyName": "My Company Name", + "productName": "Wails Vite", + "productVersion": "1.0.0", + "copyright": "Copyright.........", + "comments": "Built using Wails (https://wails.io)" + }, +``` + +アプリケーションのインストーラを生成するには、`wails build`コマンド実行時に、`-nsis`フラグを使用します: + +``` +wails build -nsis +``` + +これにより、`build/bin`ディレクトリにインストーラが生成されます。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx new file mode 100644 index 00000000000..0b47b152967 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx @@ -0,0 +1,61 @@ +# Windows + +このページでは、Windows向けのWailsアプリケーション開発に関する、様々なガイドを掲載しています。 + +## WebView2ランタイム依存関係のハンドリング + +Windows用にビルドされたWailsアプリケーションは、Microsoft [WebView2ランタイム](https://developer.microsoft.com/en-us/microsoft-edge/webview2/)がランタイム要件となっています。 Windows 11ではデフォルトでこのランタイムがインストールされていますが、一部のマシンではインストールされていません。 Wailsでは、この依存関係に対処するための簡単なアプローチを提供しています。 + +ビルド時に`-webview2`フラグを使用することで、アプリ起動時に適切なランタイムが検出されない場合(インストールされているランタイムが古すぎる場合を含む) に、アプリケーションがどのように動作するかを指定できます。 次の4つのオプションがあります: + +1. Download +2. Embed +3. Browser +4. Error + +### Download + +このオプションでは、適切なランタイムが見つからない旨をユーザに知らせ、MicrosoftのWebView2のサイトからダウンロードされる公式のブートストラッパを実行する提案をします。 ユーザが続行を選択した場合、公式のブートストラッパがダウンロードおよび実行されます。 + +### Embed + +このオプションでは、アプリケーション内に公式のブートストラッパの埋め込みます。 適切なランタイムが見つからない場合、アプリケーションはブートストラッパの実行を提案します。 これにより、バイナリサイズが150k程度増えます。 + +### Browser + +このオプションでは、適切なランタイムが見つからない旨をユーザに知らせ、ブートストラッパをダウンロードしてインストールすることのできるWebView2の公式ページをブラウザで開く提案をします。 続行した場合、アプリケーションは終了し、インストールをユーザに委ねます。 + +### Error + +このオプションでは、適切なランタイムが見つからない場合、ユーザにエラーが表示され、それ以上何の処理も実行しません。 + +## フィックスドバージョンランタイム + +WebView2の依存関係に対処するための別手段として、自身でランタイムを運ぶという方法が挙げられます。 [フィックスドバージョンランタイム](https://developer.microsoft.com/microsoft-edge/webview2/#download-section)をダウンロードしてバンドルするか、アプリケーション内でランタイムをダウンロードするようにします。 + +また、Wailsの起動時に`windows.Options`において、フィックスドバージョンWebView2ランタイムのパスを指定する必要があります。 + +```go + wails.Run(&options.App{ + Windows: &windows.Options{ + WebviewBrowserPath: "", + }, + }) +``` + +注意: `WebviewBrowserPath`が指定されている場合、必要な最低バージョンを満たしていなかったり、ランタイムへのパスが無効であったりすると、強制的に`error`オプションの挙動となります。 + +## 他のプログラムの起動 + +スクリプトなどの他のプログラムを起動すると、当該プログラムのウィンドウが画面に表示されます。 このウィンドウを表示させたくない場合は、次のコードを使用してください: + +```go +cmd := exec.Command("your_script.exe") +cmd.SysProcAttr = &syscall.SysProcAttr{ + HideWindow: true, + CreationFlags: 0x08000000, +} +cmd.Start() +``` + +この解決策は、[ディスカッションボード](https://github.com/wailsapp/wails/discussions/1734#discussioncomment-3386172)内で[sithembiso](https://github.com/sithembiso)により示されました。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx new file mode 100644 index 00000000000..00fe1d68b73 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx @@ -0,0 +1,369 @@ +--- +sidebar_position: 20 +--- + +# どうやって動いているの? + +Wailsは、webkitフロントエンドを備えた、何の変哲もないGoアプリです。 アプリ全体のうちGoの部分は、アプリのコードと、ウィンドウ制御などの便利な機能を提供するランタイムライブラリで構成されています。 フロントエンドはwebkitウィンドウであり、フロンドエンドアセットをウィンドウ上に表示します。 フロントエンドからも、JavaScriptでランタイムライブラリを呼び出すことができます。 そして最終的に、Goのメソッドはフロントエンドにバインドされ、ローカルのJavaScriptメソッドであるかのように、フロントエンドから呼び出すことができます。 + +```mdx-code-block +
+ +
+``` + +## アプリのメインコード + +### 概要 + +アプリは、`wails.Run()`メソッドを1回呼び出すことで、構成することができます。 このメソッドで、アプリのウィンドウサイズやウィンドウタイトル、使用アセットなどを指定することができます。 基本的なアプリを作るコードは次のとおりです: + +```go title="main.go" +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + + app := &App{} + + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + + +type App struct { + ctx context.Context +} + +func (b *App) startup(ctx context.Context) { + b.ctx = ctx +} + +func (b *App) shutdown(ctx context.Context) {} + +func (b *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +### オプション + +上記のコードでは、次のオプションが指定されています: + +- `Title` - ウィンドウのタイトルバーに表示されるテキスト +- `Width` & `Height` - ウィンドウの大きさ +- `Assets` - アプリのフロントエンドアセット +- `OnStartup` - ウィンドウが作成され、フロントエンドの読み込みを開始しようとする時のコールバック +- `OnShutdown` - アプリを終了しようとするときのコールバック +- `Bind` - フロントエンドにバインドさせたい構造体インスタンスのスライス + +設定可能なすべてのオプションについては、[オプションのリファレンス](reference/options)をご覧ください。 + +#### アセット + +Wailsでフロントエンドアセット無しのアプリを作成することはできないため、`Assets`オプションは必須オプションです。 アセットには、一般的なWebアプリケーションでよく見かけるような、html、js、css、svg、pngなどのファイルを含めることができます。**アセットバンドルを生成する必要は一切なく**、そのままのファイルを使用できます。 アプリが起動すると、アセット内の`index.html`が読み込まれます。この時点で、フロントエンドはブラウザとして動作するようになります。 `embed.FS`を使ってアセットファイルが格納されたディレクトリを指定しますが、ディレクトリの場所はどこでも構いません。 embedで指定するパスは、`frontend/dist`のように、アプリのメインコードから相対的に見たディレクトリパスになります: + +```go title="main.go" +//go:embed all:frontend/dist +var assets embed.FS +``` + +起動時に、Wailsは`index.html`が含まれるディレクトリを再帰的に探します。 他のすべてのアセットは、当該ディレクトリから相対的に読み込まれます。 + +本番用のバイナリファイルには、`embed.FS`で指定されたアセットファイルが含まれるため、アプリ配布時に、バイナリファイルとは別にアセットファイルを付加させる必要はありません。 + +`wails dev`コマンドを使って開発モードでアプリを起動した場合、アセットはディスクから読み込まれ、アセットファイルが更新されると、自動的にアプリがライブリロードされます。 アセットの場所は、`embed.FS`での指定値から推定されます。 + +詳細は、[アプリ開発ガイド](guides/application-development.mdx)をご覧ください。 + +#### アプリのライフサイクル + +フロントエンドが`index.html`を読み込もうとする直前に、[OnStartup](reference/options.mdx#onstartup)で指定されたメソッドがコールバックされます。 Goの標準的なcontextがこのメソッドに渡されます。 このメソッドに引数で渡されるContextは、今後、Wailsのラインタイムを呼び出すときに必要になるため、通常は、このContextへの参照を保持しておいてください。 同様に、アプリがシャットダウンされる直前には、[OnShutdown](reference/options.mdx#onshutdown)で指定されたコールバックが呼び出され、Contextも渡されます。 `index.html`に含まれるすべてのアセットが読み込み終わったときに呼び出される[OnDomReady](reference/options.mdx#ondomready)コールバックもあります。これは、JavaScriptの[`body onload`](https://www.w3schools.com/jsref/event_onload.asp)イベントと同等のものです。 また、[OnBeforeClose](reference/options.mdx#onbeforeclose)を指定すると、ウィンドウを閉じる(またはアプリを終了する)イベントにフックさせることもできます。 + +#### メソッドのバインド + +`Bind`オプションは、Wailsアプリで最も重要なオプションの1つです。 このオプションでは、フロントエンドに公開する、構造体のメソッドを指定することができます。 構造体は、従来のWebアプリにおける"コントローラ"の立ち位置であるとお考えください。 アプリが起動すると、`Bind`オプションで指定されている構造体を対象に、その中にあるパブリックメソッド(大文字で始まるメソッド名)を探します。そして、フロントエンドのコードからそれらのメソッドを呼び出せるJavaScriptが生成されます。 + +:::info 備考 + +Wailsで構造体を正しくバインドするためには、構造体の*インスタンス*をオプションで指定してください。 + +::: + +下記のコードでは、新しく`App`インスタンスを作成し、`wails.Run`関数の`Bind`オプションの中で、そのインスタンスを追加しています: + +```go {17,27} title="main.go" +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + + app := &App{} + + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + + +type App struct { + ctx context.Context +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +構造体は、好きな数だけバインドできます。 `Bind`には、構造体のインスタンスを渡すようにしてください: + +```go {10-12} + //... + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + &mystruct1{}, + &mystruct2{}, + }, + }) + +``` + +`wails dev`コマンド(または、`wails generate module`コマンド)を実行すると、以下のものを含むフロントエンドモジュールが生成されます: + +- バインドされたすべてのメソッドのJavaScript +- バインドされたすべてのメソッドのTypeScript宣言 +- バインドされたメソッドの引数または返り値で使用されているGoの構造体のTypeScript宣言 + +これにより、強力な型付けがなされたデータ構造を使用して、フロントエンドから簡単にGoのコードを呼び出すことができます。 + +## フロントエンド + +### 概要 + +フロントエンドは、webkitによってレンダリングされるファイル群です。 ブラウザとWebサーバが一体となったような動きをします。 使用できるフレームワークやライブラリの制限はほぼありません[^1]。 フロントエンドとGoコードとの相互のやり取りについて、主なポイントは次のとおりです: + +- バインドされたGoメソッドの呼び出し +- ランタイムメソッドの呼び出し + +### バインドされたGoメソッドの呼び出し + +`wails dev`コマンドでアプリを起動すると、Go構造体のJavaScriptバインディングが`wailsjs/go`ディレクトリに自動的に生成されます(`wails generate module`コマンドでも生成可能)。 生成されたファイルには、アプリ内のGoパッケージ名が反映されています。 先の例では、`Greet`というパブリックメソッドを持つ`app`をバインドしていました。 この場合、次のようなファイルが生成されることになります: + +```bash +wailsjs + └─go + └─main + ├─App.d.ts + └─App.js +``` + +ご覧のとおり、`main`パッケージ内の`App`構造体JavaScriptバインディングが、それらのメソッドのTypeScript型定義と並んで生成されていることが分かります。 フロントエンドから`Greet`メソッドを呼び出すには、単純にメソッドをインポートし、通常のJavaScript関数と同じように呼び出してください: + +```javascript +// ... +import {Greet} from '../wailsjs/go/main/App' + + function doGreeting(name) { + Greet(name).then((result) => { + // resultを使って何かする + }) + } +``` + +TypeScript型定義ファイルは、バインドされたメソッドの正しい型を提供します: + +```ts +export function Greet(arg1: string): Promise; +``` + +生成されたメソッドはPromiseを返すようになっています。 呼び出しが成功すると、Goからの1番目の返り値が`resolve`ハンドラに渡されます。 呼び出しに失敗したとみなされるのは、Goメソッドの2番目の返り値がerror型で、それがerrorインスタンスを返したときです。 これは、`reject`ハンドラを介して返されます。 先の例では、`Greet`メソッドは`string`型の返り値のみであるため、無効なデータが渡されない限り、JavaScript側でrejectハンドラが呼ばれることはありません。 + +すべてのデータ型は、GoとJavaScriptの間で正しく解釈されます。 もちろん構造体も正しく解釈されます。 Goから構造体が返された場合、フロントエンドにはJavaScriptのクラスとして返されます。 + +:::info 備考 + +TypeScript型定義を正しく自動生成するために、構造体のフィールドには、有効な`json`タグを_必ず_付与するようにしてください。 + +ネストされた匿名構造体(無名構造体) は、現時点ではサポートされていません。 + +::: + +Goに対して引数として構造体を渡すこともできます。 構造体として取り扱ってほしいJavaScriptのマップやクラスを渡すと、構造体に変換されます。 あなたが簡単にこれらのことを把握できるように、`dev`モードでは、バウンドされたGoメソッドで使用されている全構造体の型が定義された、Typescriptモジュールが生成されます。 このモジュールを使用すると、JavaScriptネイティブなオブジェクトを構築し、Goコードへ送信することができます。 + +また、シグネチャに構造体を使用するGoメソッドもサポートされています。 バインドされたメソッドで、引数または返り値として指定されているすべてのGo構造体は、Goのコードラッパーモジュールの一部として生成されたTypeScript定義を持っています。 れらを使用することで、GoとJavaScriptの間で、同じデータモデルを共有できます。 + +例: `Greet`メソッドを更新して、文字列型の代わりに`Person`型を引数で受け付けてみる: + +```go title="main.go" +type Person struct { + Name string `json:"name"` + Age uint8 `json:"age"` + Address *Address `json:"address"` +} + +type Address struct { + Street string `json:"street"` + Postcode string `json:"postcode"` +} + +func (a *App) Greet(p Person) string { + return fmt.Sprintf("Hello %s (Age: %d)!", p.Name, p.Age) +} +``` + +`wailsjs/go/main/App.js`ファイルには、次のコードが出力されます: + +```js title="App.js" +export function Greet(arg1) { + return window["go"]["main"]["App"]["Greet"](arg1); +} +``` + +しかし、`wailsjs/go/main/App.d.ts`ファイルは次のコードが出力されます: + +```ts title="App.d.ts" +import { main } from "../models"; + +export function Greet(arg1: main.Person): Promise; +``` + +見ると分かるように、"main"名前空間は、新しく生成された"models.ts"ファイルからインポートされています。 このファイルには、バインドされたメソッドで使用されるすべての構造体の型定義が含まれています。 この例では、`Person`構造体の型定義が含まれています。 `models.ts`を確認すれば、モデルがどのように定義されているかが分かります。 + +```ts title="models.ts" +export namespace main { + export class Address { + street: string; + postcode: string; + + static createFrom(source: any = {}) { + return new Address(source); + } + + constructor(source: any = {}) { + if ("string" === typeof source) source = JSON.parse(source); + this.street = source["street"]; + this.postcode = source["postcode"]; + } + } + export class Person { + name: string; + age: number; + address?: Address; + + static createFrom(source: any = {}) { + return new Person(source); + } + + constructor(source: any = {}) { + if ("string" === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.age = source["age"]; + this.address = this.convertValues(source["address"], Address); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice) { + return (a as any[]).map((elem) => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } +} +``` + +フロントエンドのビルド構成にTypescriptを使用している限り、これらのモデルを次のように使用できます: + +```js title="mycode.js" +import { Greet } from "../wailsjs/go/main/App"; +import { main } from "../wailsjs/go/models"; + +function generate() { + let person = new main.Person(); + person.name = "Peter"; + person.age = 27; + Greet(person).then((result) => { + console.log(result); + }); +} +``` + +生成されたバインディングとTypescriptモデルの組み合わせによって、強力な開発環境を実現させています。 + +バインディングの詳細については、[アプリ開発ガイド](guides/application-development.mdx)の[バインディングメソッド](guides/application-development.mdx#binding-methods)をご覧ください。 + +### ランタイムメソッドの呼び出し + +Javascriptランタイムは`window.runtime`に存在し、イベント発行やロギングなど、さまざまなタスクを実行するためのメソッドが含まれています: + +```js title="mycode.js" +window.runtime.EventsEmit("my-event", 1); +``` + +Javascriptランタイムの詳細については、[ランタイムリファレンス](reference/runtime/intro)をご覧ください。 + +[^1]: まれに、WebViewでサポートされていない機能を使用するライブラリがあります。 ほとんどの場合、それらは代替手段や回避方法がありますので、それらを検討してください。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx new file mode 100644 index 00000000000..174ffb4f88f --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx @@ -0,0 +1,75 @@ +--- +sidebar_position: 1 +--- + +# イントロダクション + +Wailsは、Go言語とWeb技術を使用して、デスクトップアプリの構築を可能にするプロジェクトです。 + +"Goの力によって、Electronが軽量かつ高速になったようなもの"、と考えるとよいでしょう。 Goの柔軟性とパワーに、リッチでモダンなフロントエンドを組み合わせたアプリを、簡単に構築することができます。 + +### 特徴 + +- ネイティブなメニュー、ダイアログ、テーマ、透過処理を使用可能です +- Windows、macOS、Linuxをサポートしています +- Svelte、React、Preact、Vue、Lit、バニラJS向けにビルトインテンプレートを用意しています +- GoメソッドをJavaScriptから簡単に呼び出せます +- Go構造体に対応するTypeScript型定義を自動生成します +- WindowsにおいてCGOや外部DLLは必要ありません +- [Vite](https://vitejs.dev/)の力を利用したライブ開発が可能です +- アプリケーションを簡単に作成、ビルド、パッケージングするための強力なCLIを備えています +- 豊富な[ランタイムライブラリ](/docs/reference/runtime/intro)を用意しています +- Wailsで構築されたアプリケーションは、Apple StoreおよびMicrosoft Storeに準拠しています + +例えば [varly](https://varly.app) は、Wailsで構築されたMacOS・Windows向けのデスクトップアプリです。 見栄えが良いだけではなく、ネイティブメニューや半透明効果を使用しています。これらは、モダンなネイティブアプリに期待されるものです。 + +```mdx-code-block +

+ + + +

+``` + +### クイックスタートテンプレート + +Wailsには、アプリの開発をすばやく始められるように、多数のテンプレートが用意されています。 Svelte、React、Vue、Preact、Lit向け、およびバニラなJavaScript用で、それぞれのテンプレートがあります。 各テンプレートには、Javascript版とTypescript版が用意されています。 + +### ネイティブ要素 + +Wailsは、ウィンドウ、メニュー、ダイアログなどのネイティブ要素を処理する専用ライブラリを使用するため、見栄えが良く、リッチな機能を備えたデスクトップアプリを構築できます。 + +**It does not embed a browser**, so it delivers a small runtime. Instead, it reuses the native rendering engine for the platform. 例えばWindowsの場合、Chromium上でビルトされているMicrosoft Webview2ライブラリを使用します。 + +### GoとJavascriptのやり取り + +Wailsは自動的に、GoのメソッドをJavascriptから利用できるようにするので、フロントエンドからGoのメソッド名を呼び出すことができます。 Goメソッドが使用する構造体を表すTypeScritpt型定義も自動生成されるため、GoとJavaScriptの間で同じデータ構造をやり取りすることができます。 + +### ランタイムライブラリ + +WailsはGoとJavascriptの両方にランタイムライブラリを提供し、イベント、ロギング、ダイアログなど、モダンなアプリに必要な多くの機能を使うことができます。 + +### ライブ開発 + +#### 自動リビルド + +アプリを"dev"モードで起動すると、Wailsはあなたが書いたコードをネイティブデスクトップアプリとしてビルドしますが、プログラムアセットは常にディスクから読み込む状態になります。 その仕組みにより、アプリ起動中にGoコードが書き換えられると、変更を検出して自動的にアプリがリビルドされ、再起動します。 + +#### 自動リロード + +フロントエンドアセットの変更が検出された場合、起動中のアプリは自動的にリロードされ、変更がすぐに反映されます。 + +#### ブラウザを使った開発 + +ブラウザでのデバッグや開発も、Wailsにお任せください。 起動中のアプリはWebサーバを兼ねており、お好きなブラウザから接続してアプリを操作することができます。 プログラムアセットが書き換わった時はすぐに更新されます。 + +### 本番用のネイティブバイナリ + +アプリを本番用にビルドする準備ができたら、CLIが、アプリを単一の実行可能ファイルへコンパイルし、すべてのアセットをバンドルしてくれます。 WindowsおよびMacOSでは、配布用のネイティブパッケージを作成できます。 パッケージ化に必要なアイコン、info.plist、マニフェストファイルなどは、プロジェクトの一部としてカスタマイズできるため、アプリのビルド方法をフルコントロールできます。 + +### ツール + +Wails CLIを使うことで、簡単にアプリを生成、ビルド、バンドルすることができます。 アイコンの作成、最適なコンパイル構成の設定、本番向けのバイナリ配布など、面倒なことをあなたの代わりに引き受けてくれます。 多数のテンプレートの中から、あなたに合ったものを選んで、すぐに開発を始めましょう! diff --git a/website/versioned_docs/version-v2.6.0/reference/_category_.json b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/_category_.json similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/_category_.json rename to website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/_category_.json diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx new file mode 100644 index 00000000000..3a7ff0a1ae5 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx @@ -0,0 +1,240 @@ +--- +sidebar_position: 2 +--- + +# CLI + +WailsのCLIには、プロジェクトの管理に使用できるコマンドが多数あります。 すべてのコマンドは次の文法で実行できます: + +`wails <コマンド> <フラグ>` + +## init + +`wails init`はプロジェクトの生成に使用します。 + +| フラグ | 説明 | デフォルト | +|:----------------- |:----------------------------------------------------------------------------- |:-------:| +| -n "プロジェクト名" | プロジェクトの名前。 **必須項目**。 | | +| -d "プロジェクトディレクトリ" | 作成するプロジェクトディレクトリ | プロジェクト名 | +| -g | gitリポジトリを初期化する | | +| -l | 利用可能なプロジェクトテンプレート一覧を表示 | | +| -q | コンソールへの出力を抑止 | | +| -t "テンプレート名" | 使用するプロジェクトテンプレート。 ここで指定する値は、デフォルトテンプレート名、または、GitHubでホストされているリモートテンプレートのURLです。 | vanilla | +| -ide | IDEプロジェクトファイルを生成 | | +| -f | アプリケーションを強制的にビルド | false | + +例: `wails init -n test -d mytestproject -g -ide vscode -q` + +この例では、サイレントモードで、"mytestproject"ディレクトリに"test"という名前のプロジェクトが生成されるとともに、gitの初期化、vscodeプロジェクトファイルの生成が行われます。 + +WailsでIDEを使用する場合の詳細については、[こちら](../guides/ides.mdx)をご覧ください。 + +### リモートテンプレート + +WailsではGitHubでホストされているリモートテンプレートをサポートしており、テンプレートのプロジェクトURLを使用してインストールできます。 + +例: `wails init -n test -t https://github.com/leaanthony/testtemplate[@v1.0.0]` + +コミュニティがメンテナンスしているテンプレートの一覧は[こちら](../community/templates.mdx)をご覧ください。 + +:::warning 注意 + +**Wailsプロジェクトでは、サードパーティ製テンプレートのメンテナンスは行っておらず、責任も負いません!** + +テンプレートについてよく分からない場合は、`package.json`および`wails.json`を確認し、どのようなスクリプトが実行されるのかや、どのようなパッケージがインストールされるのかを調べてください。 + +::: + +## build + +`wails build`は、プロジェクトを本番配布用のバイナリにコンパイルするときに使用します。 + +| フラグ | 説明 | デフォルト | +|:-------------------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |:--------------------------------------------------------------------------------------------------------------------------------------------------- | +| -clean | `build/bin`ディレクトリをクリーンする | | +| -compiler "compiler" | 違うGoコンパイラを使用する。例: go1.15beta1 | go | +| -debug | アプリケーションのデバッグ情報を保持し、デバッグコンソールを表示する。 これにより、アプリケーションウィンドウで開発者ツールを使用することを許可できます。 | | +| -devtools | Allows the use of the devtools in the application window in production (when -debug is not used). Ctrl/Cmd+Shift+F12 may be used to open the devtools window. *NOTE*: This option will make your application FAIL Mac appstore guidelines. Use for debugging only. | | +| -dryrun | 実際には実行せずにbuildコマンドの結果を表示する | | +| -f | アプリケーションを強制的にビルド | | +| -garbleargs | garbleへ渡す引数 | `-literals -tiny -seed=random` | +| -ldflags "flags" | コンパイラに渡す追加のldflags | | +| -m | コンパイル前のmod tidyの実行をスキップする | | +| -nopackage | アプリケーションをパッケージ化しない | | +| -nocolour | 出力文字に色をつけない | | +| -nosyncgomod | go.modとWailsのバージョンを同期させない | | +| -nsis | Windows向けのNSISインストーラを生成する | | +| -o filename | 出力ファイル名 | | +| -obfuscated | [garble](https://github.com/burrowers/garble)を使用してアプリケーションを難読化する | | +| -platform | 指定された[プラットフォーム](../reference/cli.mdx#platforms)(カンマ区切り) 向けにビルドする。例: `windows/arm64`。 アーキテクチャを指定しない場合は、`runtime.GOARCH`の値が使用されます。 | platform = `GOOS` environment variable if given else `runtime.GOOS`.
arch = `GOARCH` envrionment variable if given else `runtime.GOARCH`. | +| -race | Goのrace detectorを使用してビルドする | | +| -s | フロントエンドのビルドをスキップ | | +| -skipbindings | バインディングの生成をスキップする | | +| -tags "extra tags" | Goコンパイラに渡すビルドタグ。 値は引用符で囲んでください。 また、スペースまたはカンマで区切ってください(両方は使用しないでください)。 | | +| -trimpath | 実行可能ファイルから、すべてのファイルシステムパスを削除する | | +| -u | プロジェクトの`go.mod`を更新し、CLIと同じバージョンのWailsを使用する | | +| -upx | "upx"を使用して最終的にバイナリを圧縮する | | +| -upxflags | upxに渡すフラグ | | +| -v int | 詳細度レベル (0 - サイレント, 1 - デフォルト, 2 - 詳細) | 1 | +| -webview2 | WebView2インストーラーのストラテジ: download,embed,browser,error | download | +| -windowsconsole | Windiws向けビルドでコンソールウィンドウを維持する | | + +`webview2`フラグの詳細については、[Windows](../guides/windows.mdx)ガイドをご覧ください。 + +標準のGoツールを使用してビルドしたい場合は、[手動ビルド](../guides/manual-builds.mdx)ガイドをご覧ください。 + +例: + +`wails build -clean -o myproject.exe` + +:::info + +Macの場合、`Info.dev.plist`ではなく`Info.plist`がアプリケーションにバンドルされます。 + +::: + +:::info AppleシリコンでのUPX + +AppleシリコンにおけるUPXの使用には[既知の問題](https://github.com/upx/upx/issues/446)が確認されています。 + +::: + +:::info WindowsでのUPX + +いくつかのアンチウイルスソフトでは、`upx`で圧縮されたバイナリをウイルスとして検知することが確認されています。詳しくは、[upxのIssue](https://github.com/upx/upx/issues/437)をご覧ください。 + +::: + +### プラットフォーム + +サポートされているプラットフォームは次のとおりです: + +| プラットフォーム | 説明 | +|:---------------- |:-------------------------------- | +| darwin | MacOS + ビルドマシンのアーキテクチャ | +| darwin/amd64 | MacOS 10.13+ AMD64 | +| darwin/arm64 | MacOS 11.0+ ARM64 | +| darwin/universal | MacOS AMD64+ARM64 ユニバーサルアプリケーション | +| windows | Windows 10/11 + ビルドマシンのアーキテクチャ | +| windows/amd64 | Windows 10/11 AMD64 | +| windows/arm64 | Windows 10/11 ARM64 | +| linux | Linux + ビルドマシンのアーキテクチャ | +| linux/amd64 | Linux AMD64 | +| linux/arm64 | Linux ARM64 | + +## doctor + +`wails doctor`は、あなたのコンピュータで開発の準備が整っているかを診断します。 + +例: + +``` +Wails CLI v2.0.0-beta + +Scanning system - Please wait (this may take a long time)...Done. + +System +------ +OS: Windows 10 Pro +Version: 2009 (Build: 19043) +ID: 21H1 +Go Version: go1.18 +Platform: windows +Architecture: amd64 + +Dependency Package Name Status Version +---------- ------------ ------ ------- +WebView2 N/A Installed 93.0.961.52 +npm N/A Installed 6.14.15 +*upx N/A Installed upx 3.96 + +* - Optional Dependency + +Diagnosis +--------- +Your system is ready for Wails development! + +``` + +## dev + +`wails dev`は、アプリケーションを"ライブ開発"モードで実行させたいときに使用します。 このコマンドにより、次のことが行われます: + +- アプリケーションの`go.mod`が、CLIと同じバージョンのWailsを使用するように更新されます +- アプリケーションがコンパイルされた後、自動的に実行されます +- ウォッチャーが起動し、Goファイルの変更を検出した際には、アプリがリビルドされます +- `http://localhost:34115`でWebサーバが起動し、HTTP経由でアプリケーション(フロントエンドだけではありません)が提供されます。 これにより、任意のブラウザ拡張機能を使用することができます +- すべてのアプリケーションアセットはディスクから読み込まれます。 アセットが変更された場合、アプリケーションは自動的に、リビルドではなくリロードされます。 接続されているすべてのブラウザもリロードされます +- 以下のものを含むJSモジュールが生成されます: +- GoメソッドのJavaScriptラッパー (コードヒントに有用なJSDocも自動付与されています) +- Goの構造体のTypeScriptバージョン (構造体のインスタンスを生成したり、Goメソッドの引数として渡したりすることができます) +- 別のJSモジュールとして、ランタイムのラッパーおよびTS定義も生成されます +- macOSの場合、アプリケーションは`.app`ファイルにバンドルされて実行されます。 これには、開発用の`build/darwin/Info.dev.plist`を使用します。 + +| フラグ | 説明 | デフォルト | +|:---------------------------- |:----------------------------------------------------------------------------------------------------------------------------- |:--------------------- | +| -appargs "args" | シェル形式でアプリケーションに渡される引数 | | +| -assetdir "./path/to/assets" | 通常のアセットFSを使用する代わりに、指定されたディレクトリからアセットを提供する | `wails.json`で指定されている値 | +| -browser | 起動時にブラウザで`http://localhost:34115`を開く | | +| -compiler "compiler" | 違うGoコンパイラを使用する。例: go1.15beta1 | go | +| -debounce | アセットの変更が検出されたあと、リロードするまでの時間 | 100 (ミリ秒) | +| -devserver "host:port" | Wails開発サーバをバインドするアドレス | "localhost:34115" | +| -extensions | リビルドをトリガーする拡張子 (カンマ区切り) | go | +| -forcebuild | アプリケーションを強制的にビルドする | | +| -frontenddevserverurl "url" | アセットを提供するサードパーティ製の開発サーバ(例: Vite) を使用する | "" | +| -ldflags "flags" | コンパイラに渡す追加のldflags | | +| -loglevel "loglevel" | 使用するログレベル - Trace, Debug, Info, Warning, Error | Debug | +| -nocolour | CLIのカラー出力を無効にする | false | +| -noreload | アセットが変更されたときの自動リロードを無効にする | | +| -nosyncgomod | go.modとWailsのバージョンを同期させない | false | +| -race | Goのrace detectorを使用してビルドする | false | +| -reloaddirs | リロードをトリガーする追加ディレクトリ (カンマ区切り) | `wails.json`で指定されている値 | +| -s | フロントエンドのビルドをスキップ | false | +| -save | 指定された`assetdir`、`reloaddirs`、`wailsjsdir`、`debounce`、`devserver`、`frontenddevserverurl`フラグの値を、`wails.json`へ保存し、次回以降のデフォルト値にする | | +| -skipbindings | バインディングの生成をスキップする | | +| -tags "extra tags" | コンパイラへ渡すビルドタグ (引用符およびスペース区切り) | | +| -v | 詳細度レベル (0 - サイレント, 1 - デフォルト, 2 - 詳細) | 1 | +| -wailsjsdir | 生成されたWailsのJSモジュールを格納するディレクトリ | `wails.json`で指定されている値 | + +例: + +`wails dev -assetdir ./frontend/dist -wailsjsdir ./frontend/src -browser` + +この例では次のことが行われます: + +- アプリケーションをビルドして実行する (詳しくは[こちら](../guides/manual-builds.mdx)をご覧ください) +- WailsのJSモジュールを`./frontend/src`ディレクトリ内に生成する +- `./frontend/dist`ディレクトリ内のファイルの更新を監視し、変更されたときにリロードする +- ブラウザを開き、アプリケーションへ接続する + +既存のフレームワークスクリプトで本機能を使用する方法について詳しくは[こちら](../guides/application-development.mdx#live-reloading)をご覧ください。 + +## generate + +### template + +Wailsは、プロジェクトの生成に必ずテンプレートを使用します。 `wails generate template`コマンドは、プロジェクト生成時に使用できるテンプレートの作成を支援します。 + +| フラグ | 説明 | +|:---------------- |:---------------------------- | +| -name | テンプレート名 (必須項目) | +| -frontend "path" | テンプレートで使用するフロントエンドプロジェクトへのパス | + +テンプレートの作成について詳しくは、[テンプレートガイド](../guides/templates.mdx)をご覧ください。 + +### module + +`wails generate module`コマンドを使用すると、アプリケーションの`wailsjs`ディレクトリを手動で生成できます。 + +## update + +`wails update`コマンドを実行すると、Wails CLIのバージョンをアップデートできます。 + +| フラグ | 説明 | +|:------------------ |:----------------------- | +| -pre | 最新のプレリリースバージョンにアップデートする | +| -version "version" | 特定のバージョンのCLIをインストールする | + +## version + +`wails version`は、現在のCLIバージョンを出力するだけのコマンドです。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx new file mode 100644 index 00000000000..5e1f1e21808 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx @@ -0,0 +1,230 @@ +--- +sidebar_position: 4 +--- + +# メニュー + +Wailsプロジェクトに、アプリケーションメニューを追加することができます。 [Menu](#menu)構造体を定義し、アプリケーション設定の[`Menu`](../reference/options.mdx#menu)オプションへ設定するか、ランタイムの[MenuSetApplicationMenu](../reference/runtime/menu.mdx#menusetapplicationmenu)メソッドを呼び出すことで、メニューを表示させることができます。 + +メニューを作成する例: + +```go + + app := NewApp() + + AppMenu := menu.NewMenu() + FileMenu := AppMenu.AddSubmenu("File") + FileMenu.AddText("&Open", keys.CmdOrCtrl("o"), openFile) + FileMenu.AddSeparator() + FileMenu.AddText("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) { + runtime.Quit(app.ctx) + }) + + if runtime.GOOS == "darwin" { + AppMenu.Append(menu.EditMenu()) // on macos platform, we should append EditMenu to enable Cmd+C,Cmd+V,Cmd+Z... shortcut + } + + err := wails.Run(&options.App{ + Title: "Menus Demo", + Width: 800, + Height: 600, + Menu: AppMenu, // reference the menu above + Bind: []interface{}{ + app, + }, + ) + // ... +``` + +Menu構造体を更新し、[MenuUpdateApplicationMenu](../reference/runtime/menu.mdx#menuupdateapplicationmenu)メソッドを呼び出すことで、メニューを動的に更新することも可能です。 + +上記の例では、ヘルパーメソッドを使用していますが、Menu構造体を手動で構築することも可能です。 + +## Menu + +Menuは、MenuItemのコレクションです。 + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +type Menu struct { + Items []*MenuItem +} +``` + +アプリケーションメニューにおいて、各MenuItemは、"編集"などの単一メニューを表します。 + +メニューを構築するするためのシンプルなヘルパーメソッドが提供されています: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func NewMenuFromItems(first *MenuItem, rest ...*MenuItem) *Menu +``` + +これにより、コードのレイアウトが、実際のメニューと似たレイアウトになるため、メニュー項目を作成した後にそれを手動で追加するといった作業は必要なくなります。 ヘルパーを使用せず、メニュー項目を作成して手動でメニューに追加することもできます。 + +## MenuItem + +MenuItemは、メニュー内の項目を表します。 + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +// MenuItem represents a menu item contained in a menu +type MenuItem struct { + Label string + Role Role + Accelerator *keys.Accelerator + Type Type + Disabled bool + Hidden bool + Checked bool + SubMenu *Menu + Click Callback +} +``` + +| フィールド | 型 | 内容 | +| ----------- | ------------------------------------ | -------------------------------------------- | +| Label | string | メニューのテキスト | +| Accelerator | [\*keys.Accelerator](#accelerator) | このメニュー項目のキーバインディング | +| 型 | [型](#type) | メニュー項目の種類 | +| Disabled | bool | メニュー項目を無効化する | +| Hidden | bool | メニュー項目を非表示にする | +| Checked | bool | 項目にチェックを追加する (チェックボックス & ラジオタイプ) | +| SubMenu | [\*Menu](#menu) | サブメニューを設定する | +| Click | [Callback](#callback) | メニューがクリックされたときのコールバック関数 | +| Role | string | メニュー項目に[ロール](#role)を定義する。 現在のところ、Macでのみ有効です。 | + +### Accelerator + +Accelerator(キーボードショートカット) は、キーストロークとメニュー項目とのバインドを定義します。 Wailsでは、Acceleratorを、キー + [Modifier](#modifier)の組み合わせとして定義しています。 これらは`"github.com/wailsapp/wails/v2/pkg/menu/keys"`パッケージから利用可能です。 + +例: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines cmd+o on Mac and ctrl-o on Window/Linux + myShortcut := keys.CmdOrCtrl("o") +``` + +キーは、`+`を除いて、キーボード上の任意の一文字です(`+`は、`plus`で定義されています)。 いくつかのキーは一文字で表現できないため、名前付き文字のセットがあります: + +| | | | | +|:-----------:|:-----:|:-----:|:---------:| +| `backspace` | `f1` | `f16` | `f31` | +| `tab` | `f2` | `f17` | `f32` | +| `return` | `f3` | `f18` | `f33` | +| `enter` | `f4` | `f19` | `f34` | +| `escape` | `f5` | `f20` | `f35` | +| `left` | `f6` | `f21` | `numlock` | +| `right` | `f7` | `f22` | | +| `up` | `f8` | `f23` | | +| `down` | `f9` | `f24` | | +| `space` | `f10` | `f25` | | +| `delete` | `f11` | `f36` | | +| `home` | `f12` | `f37` | | +| `end` | `f13` | `f38` | | +| `page up` | `f14` | `f39` | | +| `page down` | `f15` | `f30` | | + +またWailsでは、Electronと同じ構文のAcceleratorを解析することもできます。 設定ファイルにAcceleratorを保存する際に便利です。 + +例: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines cmd+o on Mac and ctrl-o on Window/Linux + myShortcut, err := keys.Parse("Ctrl+Option+A") +``` + +#### Modifier + +ModifierはAcceleratorキーと組み合わせて使用できるキーです: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" +const ( + // CmdOrCtrlKey represents Command on Mac and Control on other platforms + CmdOrCtrlKey Modifier = "cmdorctrl" + // OptionOrAltKey represents Option on Mac and Alt on other platforms + OptionOrAltKey Modifier = "optionoralt" + // ShiftKey represents the shift key on all systems + ShiftKey Modifier = "shift" + // ControlKey represents the control key on all systems + ControlKey Modifier = "ctrl" +) +``` + +Modifierを使用してAcceleratorを作成するためのヘルパーメソッドがあります: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" +func CmdOrCtrl(key string) *Accelerator +func OptionOrAlt(key string) *Accelerator +func Shift(key string) *Accelerator +func Control(key string) *Accelerator +``` + +Modifierは`keys.Combo(key string, modifier1 Modifier, modifier2 Modifier, rest ...Modifier)`を使用して組み合わせることができます: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines "Ctrl+Option+A" on Mac and "Ctrl+Alt+A" on Window/Linux + myShortcut := keys.Combo("a", ControlKey, OptionOrAltKey) +``` + +### 型 + +各メニュー項目は5種類のうちの1タイプを指定する必要があります: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +const ( + TextType Type = "Text" + SeparatorType Type = "Separator" + SubmenuType Type = "Submenu" + CheckboxType Type = "Checkbox" + RadioType Type = "Radio" +) +``` + +使い勝手の良い、メニュー項目をすばやく作成するためのヘルパーメソッドが提供されています: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func Text(label string, accelerator *keys.Accelerator, click Callback) *MenuItem +func Separator() *MenuItem +func Radio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func Checkbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func SubMenu(label string, menu *Menu) *Menu +``` + +"Add"ヘルパーメソッドを使用して、メニューに対して直接メニュー項目を追加することも可能です: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func (m *Menu) AddText(label string, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddSeparator() *MenuItem +func (m *Menu) AddRadio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddCheckbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddSubMenu(label string, menu *Menu) *MenuI +``` + +ラジオグループに関する注意事項: ラジオグループは、メニュー内でお互いに隣接しているラジオメニュー項目同士で1つのグループとして定義されます。 つまり、手動でグループ化する必要はありません。 逆に言うと、2つのラジオグループを隣接させることはできません。ラジオグループの間には、ラジオ項目ではないメニューアイテムが必要です。 + +### Callback + +各メニュー項目には、項目がクリックされたときに呼び出されるコールバックがあります: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +type Callback func(*CallbackData) + +type CallbackData struct { + MenuItem *MenuItem +} +``` + +このコールバックには、どのメニュー項目がコールバックをトリガーしたのかを識別できる、`CallbackData`構造体が渡されます。 これは、同じコールバックを呼び出すラジオグループを作成する際などに便利です。 + +### Role + +:::info ロール + +現在、ロールはMacでのみサポートされています。 + +::: + +メニュー項目には、もともと事前に定義されたメニュー項目のロールを設定することができます。 現在サポートされているロールは次のとおりです: + +| ロール | 説明 | +| ------------ | -------------------------------------------- | +| AppMenuRole | Macアプリケーションの標準メニュー。 `menu.AppMenu()`で作成できます。 | +| EditMenuRole | Macの標準的な編集メニュー。 `menu.EditMenu()`で作成できます。 | diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx new file mode 100644 index 00000000000..2f53915a0ea --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx @@ -0,0 +1,853 @@ +--- +sidebar_position: 3 +--- + +# オプション + +## アプリケーションオプション + +`Options.App`構造体には、アプリケーションの構成設定が含まれています。 これを`wails.Run()`メソッドに渡してください: + +```go title="Example" +import ( + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/linux" + "github.com/wailsapp/wails/v2/pkg/options/mac" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +func main() { + + err := wails.Run(&options.App{ + Title: "Menus Demo", + Width: 800, + Height: 600, + DisableResize: false, + Fullscreen: false, + WindowStartState: options.Maximised, + Frameless: true, + MinWidth: 400, + MinHeight: 400, + MaxWidth: 1280, + MaxHeight: 1024, + StartHidden: false, + HideWindowOnClose: false, + BackgroundColour: &options.RGBA{R: 0, G: 0, B: 0, A: 255}, + AlwaysOnTop: false, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: assetsHandler, + Middleware: assetsMidldeware, + }, + Menu: app.applicationMenu(), + Logger: nil, + LogLevel: logger.DEBUG, + LogLevelProduction: logger.ERROR, + OnStartup: app.startup, + OnDomReady: app.domready, + OnShutdown: app.shutdown, + OnBeforeClose: app.beforeClose, + CSSDragProperty: "--wails-draggable", + CSSDragValue: "drag", + EnableDefaultContextMenu: false, + EnableFraudulentWebsiteDetection: false, + ZoomFactor: 1.0, + IsZoomControlEnabled: false, + Bind: []interface{}{ + app, + }, + ErrorFormatter: func(err error) any { return err.Error() }, + Windows: &windows.Options{ + WebviewIsTransparent: false, + WindowIsTranslucent: false, + BackdropType: windows.Mica, + DisableWindowIcon: false, + DisableFramelessWindowDecorations: false, + WebviewUserDataPath: "", + WebviewBrowserPath: "", + Theme: windows.SystemDefault, + CustomTheme: &windows.ThemeSettings{ + DarkModeTitleBar: windows.RGB(20, 20, 20), + DarkModeTitleText: windows.RGB(200, 200, 200), + DarkModeBorder: windows.RGB(20, 0, 20), + LightModeTitleBar: windows.RGB(200, 200, 200), + LightModeTitleText: windows.RGB(20, 20, 20), + LightModeBorder: windows.RGB(200, 200, 200), + }, + // ユーザへのメッセージをカスタマイズします + Messages *windows.Messages + // OnSuspendはWindowsが省電力モードに移行した場合に呼び出されます + OnSuspend func() + // OnResumeはWindowsが省電力モードから復帰した場合に呼び出されます + OnResume func(), + WebviewGpuDisabled: false, + }, + Mac: &mac.Options{ + TitleBar: &mac.TitleBar{ + TitlebarAppearsTransparent: true, + HideTitle: false, + HideTitleBar: false, + FullSizeContent: false, + UseToolbar: false, + HideToolbarSeparator: true, + }, + Appearance: mac.NSAppearanceNameDarkAqua, + WebviewIsTransparent: true, + WindowIsTranslucent: false, + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + Linux: &linux.Options{ + Icon: icon, + WindowIsTranslucent: false, + WebviewGpuPolicy: linux.WebviewGpuPolicyAlways, + ProgramName: "wails" + }, + Debug: options.Debug{ + OpenInspectorOnStartup: false, + }, + }) + + if err != nil { + log.Fatal(err) + } +} + +``` + +### Title + +ウィンドウのタイトルバーに表示されるテキストです。 + +名前: Title
データ型: `string` + +### Width + +ウィンドウの初期幅です。 + +名前: Width
データ型: `int`
デフォルト値: 1024 + +### Height + +ウィンドウの初期の高さです。 + +名前: Height
データ型: `int`
デフォルト値: 768 + +### DisableResize + +デフォルトでは、メインウィンドウのサイズは自在に変更することができます。 この設定を`true`にすると、サイズが固定されます。 + +名前: DisableResize
データ型: `bool` + +### Fullscreen + +非推奨: 代わりに[WindowStartState](#windowstartstate)を使用してください。 + +### WindowStartState + +起動時にウィンドウをどのように表示させるかを定義します。 + +| 値 | Win | Mac | Lin | +| ---------- | --- | --- | --- | +| Fullscreen | ✅ | ✅ | ✅ | +| Maximised | ✅ | ✅ | ✅ | +| Minimised | ✅ | ❌ | ✅ | + +名前: WindowStartState
データ型: `options.WindowStartState` + +### Frameless + +この設定を`true`にすると、ウィンドウに境界線やタイトルバーが表示されなくなります。 詳しくは[フレームレスウィンドウ](../guides/frameless.mdx)をご覧ください。 + +名前: Frameless
データ型: `bool` + +### MinWidth + +ウィンドウの最小幅を設定します。 `Width`の値がこの値より小さい場合、ウィンドウ幅はデフォルトで`MinWidth`の値となります。 + +名前: MinWidth
データ型: `int` + +### MinHeight + +ウィンドウの最小の高さを設定します。 `Height`の値がこの値より小さい場合、ウィンドウの高さはデフォルトで`MinHeight`の値となります。 + +名前: MinHeight
データ型: `int` + +### MaxWidth + +ウィンドウの最大幅を設定します。 `Width`の値がこの値より大きい場合、ウィンドウ幅はデフォルトで`MaxWidth`の値となります。 + +名前: MaxWidth
データ型: `int` + +### MaxHeight + +ウィンドウの最大の高さを設定します。 `Height`の値がこの値より大きい場合、ウィンドウの高さはデフォルトで`MaxHeight`の値となります。 + +名前: MaxHeight
データ型: `int` + +### StartHidden + +`true`に設定すると、アプリケーションは[WindowShow](../reference/runtime/window.mdx#windowshow)が呼び出されるまで非表示となります。 + +名前: StartHidden
データ型: `bool` + +### HideWindowOnClose + +デフォルトでは、ウィンドウを閉じるとアプリケーションが終了します。 この設定を`true`にすると、ウィンドウを閉じる操作をした際に、 + +ウィンドウが非表示の状態になります。 + +名前: HideWindowOnClose
データ型: `bool` + +### BackgroundColour + +ウィンドウのデフォルトの背景色です。 例: options.NewRGBA(255,0,0,128) - 50%透過された赤色 + +名前: BackgroundColour
データ型: `*options.RGBA`
デフォルト値: white + +### AlwaysOnTop + +ウィンドウへのフォーカスが無くなっても、他ウィンドウより手前側にウィンドウを表示させるかを設定します。 + +名前: AlwaysOnTop
データ型: `bool` + +### Assets + +非推奨: 代わりに[AssetServerの固有オプション](#assetserver)であるAssetsオプションを使用してください。 + +### AssetsHandler + +非推奨: 代わりに[AssetServerの固有オプション](#assetserver)であるAssetsHandlerオプションを使用してください。 + +### AssetServer + +AssetServerの固有オプションを定義します。 静的なアセットでAssetServerをカスタマイズしたり、`http.Handler`で動的なアセットを提供したり、`assetserver.Middleware`でリクエストチェーンにフックしたりすることができます。 + +現在のところ、`http.Request`のすべての機能がサポートされているわけではありません。次の機能マトリクスを確認してください: + +| 機能 | Win | Mac | Lin | +| ----------------------- | --- | --- | ------ | +| GET | ✅ | ✅ | ✅ | +| POST | ✅ | ✅ | ✅ [^1] | +| PUT | ✅ | ✅ | ✅ [^1] | +| PATCH | ✅ | ✅ | ✅ [^1] | +| DELETE | ✅ | ✅ | ✅ [^1] | +| Request Headers | ✅ | ✅ | ✅ [^1] | +| Request Body | ✅ | ✅ | ✅ [^2] | +| Request Body Streaming | ✅ | ✅ | ✅ [^2] | +| Response StatusCodes | ✅ | ✅ | ✅ [^1] | +| Response Headers | ✅ | ✅ | ✅ [^1] | +| Response Body | ✅ | ✅ | ✅ | +| Response Body Streaming | ❌ | ✅ | ✅ | +| WebSockets | ❌ | ❌ | ❌ | +| HTTP Redirects 30x | ✅ | ❌ | ❌ | + +名前: AssetServer
データ型: `*assetserver.Options` + +#### Assets + +アプリケーションのフロントエンドで使用される静的アセットです。 + +GETリクエストが要求された場合、まず初めに、この`fs.FS`からのアセット提供を試みます。 `fs.FS`から、当該ファイルが存在しない旨の`os.ErrNotExist`エラーが返された場合、このリクエストは[Handler](#handler)へフォールバックされ、ハンドラ側でGETリクエストへの応答を試みます。 + +nilがセットされている場合、GETリクエストに常に[Handler](#handler)へ転送されます。 + +名前: Assets
データ型: `fs.FS` + +#### Handler + +アセットハンドラは、アセットが見つからなかった場合のフォールバック処理を担う、ジェネリックな`http.Handler`です。 + +[Assets](#assets)内で`os.ErrNotExist`エラーが発生したことにより、アセットを提供できないと判断されたすべてのGETリクエストによって、このハンドラが呼び出されます。 また、GET以外のすべての種類のリクエストは、常にこのハンドラから応答が返されます。 ハンドラが定義されていない状態で、ハンドラが呼び出された場合、次の応答が返されます: + +- GETリクエスト: `http.StatusNotFound` +- その他のリクエスト: `http.StatusMethodNotAllowed` + +注意: フロントエンド側の開発サーバと組み合わせて使用すると、一部制限がかかる場合があります。 Viteは、拡張子を含まないパスに対して、常にindex.htmlを返します。 + +名前: AssetsHandler
データ型: `http.Handler` + +#### Middleware + +MiddlewareはHTTPミドルウェアで、AssetServerのリクエストチェーンをフックすることができます。 例えば、特殊なルーティングを実装したいときなど、デフォルトのリクエストハンドラを動的にスキップさせることができます。 Middlewareは、AssetSeverが使用する新しい`http.Handler`を生成するために呼び出されます。引数では、AssetServerがデフォルトで使用するハンドラを受け取ります。 + +Middlewareが定義されていない場合、デフォルトのAssetServerのリクエストチェーンが実行されます。 + +名前: Middleware
データ型: `assetserver.Middleware` + +### Menu + +アプリケーションで使用されるメニューです。 メニューについて詳しくは、[メニューのリファレンス](../reference/runtime/menu.mdx)をご覧ください。 + +:::note + +Macでは、メニューが指定されていない場合、デフォルトメニューが作成されます。 + +::: + +名前: Menu
データ型: `*menu.Menu` + +### Logger + +アプリケーションで使用するロガーです。 ロギングについて詳しくは、[ログのリファレンス](../reference/runtime/log.mdx)をご覧ください。 + +名前: Logger
データ型: `logger.Logger`
デフォルト値: 標準出力へのロガー + +### LogLevel + +デフォルトのログレベルです。 ロギングについて詳しくは、[ログのリファレンス](../reference/runtime/log.mdx)をご覧ください。 + +名前: LogLevel
データ型: `logger.LogLevel`
デフォルト値: 開発モードの場合は`Info`、本番モードの場合は`Error` + +### LogLevelProduction + +本番ビルド時のデフォルトのログレベルです。 ロギングについて詳しくは、[ログのリファレンス](../reference/runtime/log.mdx)をご覧ください。 + +名前: LogLevelProduction
データ型: `logger.LogLevel`
デフォルト値: `Error` + +### OnStartup + +フロントエンド作成後、`index.html`が読み込まれる前に呼び出されるコールバックです。 アプリケーションのcontextが渡されます。 + +名前: OnStartup
データ型: `func(ctx context.Context)` + +### OnDomReady + +フロントエンドが`index.html`とそのリソースを読み込んだ後に呼び出されるコールバックです。 アプリケーションのcontextが渡されます。 + +名前: OnDomReady
データ型: `func(ctx context.Context)` + +### OnShutdown + +フロントエンドが破棄され、アプリケーションが終了する直前に呼び出されるコールバックです。 アプリケーションのcontextが渡されます。 + +名前: OnShutdown
データ型: `func(ctx context.Context)` + +### OnBeforeClose + +ウィンドウの閉じるボタンをクリックするか、`runtime.Quit`が呼ばれて、アプリケーションが終了されそうになっているときに呼び出されるコールバックです。 trueを返すとアプリケーションはそのまま維持され、falseを返すと通常どおりシャットダウンされます。 ユーザに対してプログラムの終了を確認したいときは、このコールバックを使うのが良いでしょう。 + +例: + +```go title=windowsapp.go +func (b *App) beforeClose(ctx context.Context) (prevent bool) { + dialog, err := runtime.MessageDialog(ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Quit?", + Message: "Are you sure you want to quit?", + }) + + if err != nil { + return false + } + return dialog != "Yes" +} +``` + +名前: OnBeforeClose
データ型: `func(ctx context.Context) bool` + +### CSSDragProperty + +ウィンドウをドラッグできる要素を特定するためのCSSプロパティ名を設定します。 デフォルト値: `--wails-draggable` + +名前: CSSDragProperty
データ型: `string` + +### CSSDragValue + +ウィンドウのドラッグを有効にするために、`CSSDragProperty`スタイルが持つべき値を設定します。 デフォルト値: `drag` + +名前: CSSDragValue
データ型: `string` + +### EnableDefaultContextMenu + +EnableDefaultContextMenuは、本番環境において、ブラウザのデフォルトコンテキストメニューを有効にします。 + +By default, the browser's default context-menu is only available in development and in a `-debug` [build](../reference/cli.mdx#build) along with the devtools inspector, Using this option you can enable the default context-menu in `production` while the devtools inspector won't be available unless the `-devtools` build flag is used. + +このオプションを有効にすると、デフォルトでは、テキストに関するコンテキスト(切り取り/コピー/貼り付け) のみがコンテキストメニューに表示されます。この動作をオーバーライドするには、`--default-contextmenu`というCSSプロパティを任意のHTML要素(`body`含む) で以下の値と共に使用してください: + +| CSSスタイル | 動作 | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | +| `--default-contextmenu: auto;` | (**デフォルト**) 次の場合にのみデフォルトのコンテキストメニューを表示します:
contentEditableがtrueである、またはテキストが選択されている、またはinput要素/textarea要素であるとき | +| `--default-contextmenu: show;` | 常にデフォルトのコンテキストメニューを表示します | +| `--default-contextmenu: hide;` | 常にデフォルトのコンテキストメニューを非表示にします | + +このルールは通常のCSSルールと同様に継承されるため、ネストも期待どおりに動作します。 + +:::note +このフィルタリング機能は本番環境でのみ有効であり、開発・デバッグビルドでは、フルコンテキストメニューが常に使用できます。 +::: + +:::warning +このフィルタリング機能はセキュリティ対策として使用することはできません。開発者は、画像のダウンロード、リロード、ウェブページの保存といったコマンドを含むフルコンテキストメニューが常にリークされる可能性を考慮すべきです。この点が気になる場合、開発者はデフォルトのコンテキストメニューを有効にするべきではありません。 +::: + + +名前: EnableDefaultContextMenu
データ型: `bool` + +### EnableFraudulentWebsiteDetection + +EnableFraudulentWebsiteDetectionは、マルウェアやフィッシング詐欺などの不正コンテンツのスキャンサービスを有効にします。 これらのサービスは、ナビゲートされたURLやその他コンテンツ情報を、アプリからAppleおよびMicrosoftのクラウドサービスに送信する可能性があります。 + +名前: EnableFraudulentWebsiteDetection
データ型: `bool` + +### ZoomFactor + +名前: ZoomFactor
データ型: `float64` + +WebView2の拡大率を定義します。 これは、Edgeのユーザによるズームインまたはズームアウトに対応するオプションです。 + +### IsZoomControlEnabled + +名前: IsZoomControlEnabled
データ型: `bool` + +このオプションを有効にすると、拡大率をユーザによって変更することができます。 拡大率の変更がユーザに許可されていない間は、オプションで拡大率を設定することができますのでご注意ください (例: キオスクアプリケーションなど)。 + +### Bind + +フロントエンドにバインドする必要があるメソッドが定義された、構造体インスタンスのスライスです。 + +名前: Bind
データ型: `[]interface{}` + +### ErrorFormatter + +JSからGoへ呼び出されたメソッドがエラーを返す際に、エラーをフォーマットする関数です。 返り値はJSONとして変換されます。 + +名前: ErrorFormatter
データ型: `func (error) any` + +### Windows + +[Windows固有のオプション](#windows)を定義します。 + +名前: Windows
データ型: `*windows.Options` + +#### WebviewIsTransparent + +この値を`true`に設定すると、アルファ値が`0`の際に、WebViewの背景が透明になります。 つまり、CSSで`background-color`に`rgba(0,0,0,0)`を設定すると、ホストウィンドウが透けて見えるようになります。 多くの場合、[WindowIsTranslucent](#WindowIsTranslucent)と組み合わて、霜のように見えるアプリケーションを作成する際に使用します。 + +名前: WebviewIsTransparent
データ型: `bool` + +#### WindowIsTranslucent + +この値を`true`に設定すると、ウィンドウの背景が半透明になります。 多くの場合、[WebviewIsTransparent](#WebviewIsTransparent)と組み合わせて使用されます。 + +ビルド22621より前のWindows 11の場合、半透明を実現させるために[BlurBehind](https://learn.microsoft.com/ja-jp/windows/win32/dwm/blur-ovw)メソッドを使用するため、処理が遅くなる可能性があります。 ビルド22621以降のWindows 11では、より高速な、新しい半透明タイプが有効になります。 デフォルトで使用される半透明タイプは、Windowsにより決定されます。 このタイプを設定するには、[BackdropType](#BackdropType)オプションを使用してください。 + +名前: WindowIsTranslucent
データ型: `bool` + +#### BackdropType + +:::note + +この設定を適用するには、Windows 11 ビルド22621以降が必要です。 + +::: + +ウィンドウの半透明タイプを設定します。 この設定は、[WindowIsTranslucent](#WindowIsTranslucent)が`true`に設定されている場合にのみ適用されます。 + +名前: BackdropType
データ型: `windows.BackdropType` + +値は次のいずれかを指定してください: + +| 値 | 説明 | +| ------- | ----------------------------------------------------------------------------------- | +| Auto | Windowsに背景を決定させる | +| None | 半透明にしない | +| Acrylic | [アクリル](https://learn.microsoft.com/ja-jp/windows/apps/design/style/acrylic)の効果を使用する | +| Mica | [マイカ](https://learn.microsoft.com/ja-jp/windows/apps/design/style/mica)の効果を使用する | +| Tabbed | タブを使用する。 これはマイカに似ている背景です。 | + +#### DisableWindowIcon + +この設定を`true`にすると、タイトルバーの左上隅のアイコンが消去されます。 + +名前: DisableWindowIcon
データ型: `bool` + +#### DisableFramelessWindowDecorations + +この設定を`true`にすると、[フレームレス](#Frameless)モードでのウィンドウデコレーションが消去されます。 つまり、'Aero Shadow'および'Rounded Corners'がウィンドウに適用されなくなります。 なお、'Rounded Corners'はWindows 11でのみサポートされていますのでご注意ください。 + +名前: DisableFramelessWindowDecorations
データ型: `bool` + +#### WebviewUserDataPath + +WebView2が、ユーザデータを格納するパスを設定します。 空の場合は、`%APPDATA%\[BinaryName.exe]`が使用されます。 + +名前: WebviewUserDataPath
データ型: `string` + +#### WebviewBrowserPath + +WebView2の実行ファイルおよびライブラリが存在するディレクトリへのパスを設定します。 空の場合、システムにインストールされているWebView2が使用されます。 + +固定バージョンランタイムディストリビューションに関する重要情報: + +- [ランタイムの取得および展開方法](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#details-about-the-fixed-version-runtime-distribution-mode) +- [固定バージョンに関する既知の問題](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#known-issues-for-fixed-version) +- [WenView2ランタイムの固定バージョンのパスに、\Edge\Application\ を含めてはいけません](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.1245.22#createcorewebview2environmentwithoptions) + +名前: WebviewBrowserPath
データ型: `string` + +#### Theme + +サポートされるWindowsの最小バージョン: Windows 10 2004/20H1 + +アプリケーションが使用するテーマを設定します: + +| 値 | 説明 | +| ------------- | ---------------------------------------------------------------------------------------- | +| SystemDefault | _デフォルト値_です。 テーマは、システムのデフォルト設定に基づきます。 ユーザがシステムのテーマ設定を変更した場合、アプリケーションは新しい設定を使用するように更新されます。 | +| Dark | アプリケーションはダークテーマのみを使用します。 | +| Light | アプリケーションはライトテーマのみを使用します。 | + +名前: Theme
データ型: `windows.Theme` + +#### CustomTheme + +:::note + +サポートされるWindowsの最小バージョン: Windows 10/11 2009/21H2 ビルド22000 + +::: + +ウィンドウがアクティブまたは非アクティブのときに、ライトモード・ダークモードのそれぞれにおいて、タイトルバー、タイトルテキスト、ボーダーのカスタムカラーを設定できます。 + +名前: CustomTheme
データ型: `windows.CustomTheme` + +##### CustomTheme 型 + +CustomTheme構造体は、`int32`型で色の値を指定します。 これは`0x00BBGGAA`で表されるWindowsの標準フォーマットで指定します。 RGBの値をこのフォーマットに変換するために、`windows.RGB(r,g,b uint8)`のようなヘルパー関数が用意されています。 + +注意: 指定されていない値はデフォルトで黒色になります。 + +```go +type ThemeSettings struct { + DarkModeTitleBar int32 + DarkModeTitleBarInactive int32 + DarkModeTitleText int32 + DarkModeTitleTextInactive int32 + DarkModeBorder int32 + DarkModeBorderInactive int32 + LightModeTitleBar int32 + LightModeTitleBarInactive int32 + LightModeTitleText int32 + LightModeTitleTextInactive int32 + LightModeBorder int32 + LightModeBorderInactive int32 +} +``` + +例: + +```go + CustomTheme: &windows.ThemeSettings{ + // Theme to use when window is active + DarkModeTitleBar: windows.RGB(255, 0, 0), // Red + DarkModeTitleText: windows.RGB(0, 255, 0), // Green + DarkModeBorder: windows.RGB(0, 0, 255), // Blue + LightModeTitleBar: windows.RGB(200, 200, 200), + LightModeTitleText: windows.RGB(20, 20, 20), + LightModeBorder: windows.RGB(200, 200, 200), + // Theme to use when window is inactive + DarkModeTitleBarInactive: windows.RGB(128, 0, 0), + DarkModeTitleTextInactive: windows.RGB(0, 128, 0), + DarkModeBorderInactive: windows.RGB(0, 0, 128), + LightModeTitleBarInactive: windows.RGB(100, 100, 100), + LightModeTitleTextInactive: windows.RGB(10, 10, 10), + LightModeBorderInactive: windows.RGB(100, 100, 100), + }, +``` + +#### Messages + +利用可能なWebView2ランタイムが見つからなかったときに表示する、WebView2インストーラに関するメッセージ文字列を設定します。 + +名前: Messages
データ型: `*windows.Messages` + +プロジェクトがサポートする言語にあわせて、この設定をカスタマイズしてください。 + +#### ResizeDebounceMS + +ResizeDebounceMSは、ウィンドウサイズが変更されたときに、WebView2の再描画を実行するまでの時間です。 デフォルト値(0) は、できるだけ早く再描画を実行します。 + +名前: ResizeDebounceMS
データ型: `uint16` + +#### OnSuspend + +Windowsがローパワーモード(サスペンド/休止状態) に切り替わると呼び出されるコールバックを設定します。 + +名前: OnSuspend
データ型: `func()` + +#### OnResume + +Windowsがローパワーモード(サスペンド/休止状態) から復帰したときに呼び出されるコールバックを設定します。 + +名前: OnResume
データ型: `func()` + +#### WebviewGpuIsDisabled + +`true`に設定すると、webviewのGPUハードウェアアクセラレーションが無効化されます。 + +名前: WebviewGpuIsDisabled
データ型: `bool` + +#### EnableSwipeGestures + +Setting this to `true` will enable swipe gestures for the webview. + +Name: EnableSwipeGestures
Type: `bool` + +### Mac + +[Mac固有のオプション](#mac)を定義します。 + +名前: Mac
データ定義: `*mac.Options` + +#### TitleBar + +TitleBar構造体は、タイトルバーのルック・アンド・フィールを設定する機能を提供します。 + +名前: TitleBar
データ型: [`*mac.TitleBar`](#titlebar-struct) + +##### Titlebar 構造体 + +アプリケーションのタイトルバーは、TitleBarオプションを使用することでカスタマイズできます: + +```go +type TitleBar struct { + TitlebarAppearsTransparent bool + HideTitle bool + HideTitleBar bool + FullSizeContent bool + UseToolbar bool + HideToolbarSeparator bool +} +``` + +| 名前 | 説明 | +| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| TitlebarAppearsTransparent | タイトルバーを透明にします。 これにより、タイトルバーが非表示になり、コンテンツがウィンドウ全体に表示されます。 [Appleドキュメント](https://developer.apple.com/documentation/appkit/nswindow/1419167-titlebarappearstransparent?language=objc) | +| HideTitle | ウィンドウタイトルを非表示にします。 [Appleドキュメント](https://developer.apple.com/documentation/appkit/nswindowtitlevisibility?language=objc) | +| HideTitleBar | スタイルマスクから[NSWindowStyleMaskTitled](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemasktitled/)を消去します。 | +| FullSizeContent | WebViewをウィンドウ全体に表示します。 [Appleドキュメント](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemaskfullsizecontentview) | +| UseToolbar | ウィンドウにデフォルトツールバーを追加します。 [Appleドキュメント](https://developer.apple.com/documentation/appkit/nstoolbar?language=objc) | +| HideToolbarSeparator | ツールバーの下側の線を消去します。 [Appleドキュメント](https://developer.apple.com/documentation/appkit/nstoolbar/1516954-showsbaselineseparator?language=objc) | + +事前設定されたタイトルバー構成を利用することも可能です: + +| 設定 | 例 | +| --------------------------- | ---------------------------------------------- | +| `mac.TitleBarDefault()` | ![](/img/reference/titlebar-default.webp) | +| `mac.TitleBarHidden()` | ![](/img/reference/titlebar-hidden.webp) | +| `mac.TitleBarHiddenInset()` | ![](/img/reference/titlebar-hidden-inset.webp) | + +例: + +```go +Mac: &mac.Options{ + TitleBar: mac.TitleBarHiddenInset(), +} +``` + +タイトルバーのカスタマイズに関してインスピレーションを得たい場合は[こちら](https://github.com/lukakerr/NSWindowStyles)をご覧ください。 + +#### Appearance + +Appearanceは、Appleの[NSAppearance](https://developer.apple.com/documentation/appkit/nsappearancename?language=objc)Nameに従って、アプリケーションのスタイルを設定するために使用します。 + +名前: Appearance
データ型: [`mac.AppearanceType`](#appearance-type) + +##### Appearance 型 + +アプリケーションの[外観](https://developer.apple.com/documentation/appkit/nsappearance?language=objc)を指定します。 + +| 値 | 説明 | +| ----------------------------------------------------- | ------------------------------------- | +| DefaultAppearance | DefaultAppearanceは、システムのデフォルト値を使用します。 | +| NSAppearanceNameAqua | システムの標準的なライト外観 | +| NSAppearanceNameDarkAqua | システムの標準的なダーク外観 | +| NSAppearanceNameVibrantLight | より鮮やかなライト外観 | +| NSAppearanceNameAccessibilityHighContrastAqua | システムの標準的なライト外観のハイコントラスト版 | +| NSAppearanceNameAccessibilityHighContrastDarkAqua | システムの標準的なダーク外観のハイコントラスト版 | +| NSAppearanceNameAccessibilityHighContrastVibrantLight | より鮮やかなライト外観のハイコントラスト版 | +| NSAppearanceNameAccessibilityHighContrastVibrantDark | より鮮やかなダーク外観のハイコントラスト版 | + +例: + +```go +Mac: &mac.Options{ + Appearance: mac.NSAppearanceNameDarkAqua, +} +``` + +#### WebviewIsTransparent + +この値を`true`に設定すると、アルファ値が`0`の際に、WebViewの背景が透明になります。 つまり、CSSで`background-color`に`rgba(0,0,0,0)`を設定すると、ホストウィンドウが透けて見えるようになります。 多くの場合、[WindowIsTranslucent](#WindowIsTranslucent)と組み合わて、霜のように見えるアプリケーションを作成する際に使用します。 + +名前: WebviewIsTransparent
データ型: `bool` + +#### WindowIsTranslucent + +この値を`true`に設定すると、ウィンドウの背景が半透明になります。 多くの場合、[WebviewIsTransparent](#WebviewIsTransparent)と組み合わて、霜のように見えるアプリケーションを作成する際に使用します。 + +名前: WindowIsTranslucent
データ型: `bool` + +#### Preferences + +The Preferences struct provides the ability to configure the Webview preferences. + +Name: Preferences
Type: [`*mac.Preferences`](#preferences-struct) + +##### Preferences struct + +You can specify the webview preferences. + +```go +type Preferences struct { + TabFocusesLinks u.Bool + TextInteractionEnabled u.Bool + FullscreenEnabled u.Bool +} +``` + +| 名前 | 説明 | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| TabFocusesLinks | A Boolean value that indicates whether pressing the tab key changes the focus to links and form controls. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/2818595-tabfocuseslinks?language=objc) | +| TextInteractionEnabled | A Boolean value that indicates whether to allow people to select or otherwise interact with text. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3727362-textinteractionenabled?language=objc) | +| FullscreenEnabled | A Boolean value that indicates whether a web view can display content full screen. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3917769-elementfullscreenenabled?language=objc) | + +例: + +```go +Mac: &mac.Options{ + Preferences: &mac.Preferences{ + TabFocusesLinks: mac.Enabled, + TextInteractionEnabled: mac.Disabled, + FullscreenEnabled: mac.Enabled, + } +} +``` + +#### About + +"AppMenu"ロールで作成されたアプリケーションメニューの中にある"About"メニュー項目において、タイトル、メッセージ、アイコンを設定できます。 + +名前: About
データ型: [`*mac.AboutInfo`](#about-struct) + +##### About 構造体 + +```go + +type AboutInfo struct { + Title string + Message string + Icon []byte +} +``` + +これらの設定が定義されている場合、`AppMenu`ロールが使用されていれば、アプリケーションメニュー内に"About"メニューが表示されます。 例えば以下のように設定すると: + +```go +//go:embed build/appicon.png +var icon []byte + +func main() { + err := wails.Run(&options.App{ + ... + Mac: &mac.Options{ + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + }) +``` + +アプリケーションメニューに"About"メニュー項目が表示されます: + +```mdx-code-block +
+ +
+
+``` + +クリックすると、アプリケーション概要メッセージボックスが開かれます: + +```mdx-code-block +
+ +
+
+``` + +### Linux + +[Linux固有のオプション](#linux)を定義します。 + +名前: Linux
データ型: `*linux.Options` + +#### Icon + +ウィンドウを示すアイコンを設定します。 このアイコンは、ウィンドウが最小化されたときに使用されます(iconifiedと呼ばれます)。 + +名前: Icon
データ型: `[]byte` + +一部のウィンドウマネージャやデスクトップ環境では、ウィンドウフレームに配置されたり、他のコンテキストで表示される場合もあります。 反対に、環境によっては全くアイコンが使用されないこともありますのでご注意ください。 + +注意: 少なくともWayland上のGnomeでは、このアイコンは表示されません。 アプリケーションアイコンを表示させるには、`.desktop`ファイルを使用する必要があります。 KDEの場合は正常に表示されるはずです。 + +アイコンは、何の加工もされていないサイズで用意してください。つまり、拡大/縮小された画像は使用しないでください。 最高品質を確保するために、拡大/縮小は、最終的な目的サイズがはっきりするまで待ってください。 + +#### WindowIsTranslucent + +この値を`true`に設定すると、ウィンドウの背景が半透明になります。 ウィンドウマネージャによっては、この設定を無視したり、ブラックウィンドウになる場合があります。 + +名前: WindowIsTranslucent
データ型: `bool` + +#### WebviewGpuPolicy + +このオプションでは、webviewのハードウェアアクセラレーションポリシーを指定することができます。 + +名前: WebviewGpuPolicy
データ型: [`options.WebviewGpuPolicy`](#webviewgpupolicy-type)
デフォルト値: `WebviewGpuPolicyAlways` + +##### WebviewGpuPolicy型 + +| 値 | 説明 | +| ------------------------ | --------------------------------------------- | +| WebviewGpuPolicyAlways | ハードウェアアクセラレーションを常に有効にする | +| WebviewGpuPolicyOnDemand | Webコンテンツからの要求に応じて、ハードウェアアクセラレーションの有効/無効を切り替える | +| WebviewGpuPolicyNever | ハードウェアアクセラレーションを常に無効にする | + +#### ProgramName + +このオプションでは、GTKのg_set_prgname() を使用し、ウィンドウマネージャのプログラム名を設定することができます。 ただし、ローカライズされた名前を設定すべきではありません。詳しくは[ドキュメント](https://docs.gtk.org/glib/func.set_prgname.html)をご覧ください。 + +.desktopファイルが作成される際、.desktopファイルの`Name`オプションと実行ファイルのファイル名が異なる場合に、ウィンドウのグループ化およびデスクトップアイコンの表示に、本オプションは役立ちます。 + +名前: ProgramName
データ型: string
+ +### Debug + +デバッグビルド時に適用される[デバッグ固有のオプション](#Debug)を定義します。 + +名前: Debug
データ型: `options.Debug` + +#### OpenInspectorOnStartup + +このオプションを`true`に設定すると、アプリケーション起動時にWeb開発者ツールが表示されます。 + +名前: OpenInspectorOnStartup
データ型: `bool` + +[^1]: この機能の動作には、WebKit2GTK 2.36以上が必要となるため、機能を確実に対応させたい場合は、アプリビルド時にビルドタグ`webkit2_36`を付与してください。 これにより、アプリに必要なWebKit2GTKの最小バージョン要件が2.36に引き上げられます。 +[^2]: この機能の動作には、WebKit2GTK 2.40以上が必要となるため、機能を確実に対応させたい場合は、アプリビルド時にビルドタグ`webkit2_40`を付与してください。 これにより、アプリに必要なWebKit2GTKの最小バージョン要件が2.40に引き上げられます。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx new file mode 100644 index 00000000000..514c48c4ca9 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx @@ -0,0 +1,91 @@ +--- +sidebar_position: 5 +--- + +# プロジェクト構成 + +プロジェクト構成は、プロジェクトディレクトリ内の`wails.json`ファイルで設定します。 ファイルの構造は次のとおりです: + +```json5 +{ + // プロジェクト構成のバージョン。 + "version": "", + // プロジェクト名。 + "name": "", + // コンパイルされたアセットディレクトリへの相対パス。通常は自動的に推測されるため、空で構いません。 + "assetdir": "", + // 再読み込みのトリガーとなる追加のディレクトリ(カンマ区切り)。高度なアセット構成をとる場合にのみ使用します。 + "reloaddirs": "", + // ビルドファイルが存在するディレクトリ。 デフォルトは'build'です。 + "build:dir": "", + // フロントエンドディレクトリの相対パス。 デフォルトは'frontend'です。 + "frontend:dir": "", + // node依存関係をインストールするために、フロントエンドディレクトリで実行するコマンド。一般的には`npm install`です。 + "frontend:install": "", + // アセットをビルドするために、フロントエンドディレクトリで実行するコマンド。一般的には`npm run build`です。 + "frontend:build": "", + // このコマンドはfrontend:dev:buildへ置換されました。 frontend:dev:buildが指定されていない場合は、代わりにこのコマンドが実行されます。 このコマンドも指定されていない場合は、代わりにfrontend:buildが実行されます。 + "frontend:dev": "", + // 開発モードにおけるfrontend:buildと同様のコマンド。 指定されていない場合は、代わりにfrontend:devが実行されます。 + "frontend:dev:build": "", + // 開発モードにおけるfrontend:installと同様のコマンド。 指定されていない場合は、代わりにfrontend:installが実行されます。 + "frontend:dev:install": "", + // `wails dev`実行時に別プロセスで実行するコマンド。 サードパーティ製のウォッチャや開発サーバを起動したい場合に便利です。 + "frontend:dev:watcher": "", + // Viteなど、アセットを提供するサードパーティ製の開発サーバのURL。 'auto'に設定すると、Viteの出力から自動的に開発サーバURLを推測します。 + "frontend:dev:serverUrl": "", + // 自動生成されるJSモジュールを出力するディレクトリへの相対パス。 + "wailsjsdir": "", + // 出力バイナリのファイル名 + "outputfilename": "", + // アセットファイルに変更があった場合に、開発サーバが再読み込みを行うまでのデフォルトの待ち時間。 + "debounceMS": 100, + // Wailsの開発サーバをバインドするアドレス。 デフォルト値: localhost:34115 + "devServer": "", + // 開発モードのときに、アプリケーションに渡されるシェルスタイルの引数。 + "appargs": "", + // ホストOS以外のOS用にビルドフックが定義されている場合、それらを実行するかどうか。 + "runNonNativeBuildHooks": false, + "preBuildHooks": { + // 指定されたGOOS/GOARCHのビルドの前に実行されるコマンド。${platform}は'GOOS/GOARCH'に置換されます。 'GOOS/GOARCH'フックは、'GOOS/*'および'*/*'フックの前に実行されます。 + "GOOS/GOARCH": "", + // 指定されたGOOSのビルド前に実行されるコマンド。${platform}は'GOOS/GOARCH'に置換されます。 'GOOS/*'フックは、'*/*'フックの前に実行されます。 + "GOOS/*": "", + // 毎回のビルドの前に実行されるコマンド。${platform}は'GOOS/GOARCH'に置換されます。 + "*/*": "" + }, + "postBuildHooks": { + // 指定されたGOOS/GOARCHのビルドの後に実行されるコマンド。${platform}は'GOOS/GOARCH'に置換され、${bin}はコンパイル済みバイナリへのパスに置換されます。 'GOOS/GOARCH'フックは、'GOOS/*'および'*/*'フックの前に実行されます。 + "GOOS/GOARCH": "", + // 指定されたGOOSのビルド後に実行されるコマンド。${platform}は'GOOS/GOARCH'に置換され、${bin}はコンパイル済みバイナリへのパスに置換されます。 'GOOS/*'フックは、'*/*'フックの前に実行されます。 + "GOOS/*": "", + // 毎回のビルドの後に実行されるコマンド。${platform}は'GOOS/GOARCH'に置換され、${bin}はコンパイル済みバイナリへのパスに置換されます。 + "*/*": "" + }, + // マニフェストやバージョン情報で使用されるデータ。 + "info": { + // 会社名。 デフォルト値: [プロジェクト名] + "companyName": "", + // 製品名。 デフォルト値: [プロジェクト名] + "productName": "", + // 製品バージョン。 デフォルト値: '1.0.0'] + "productVersion": "", + // 製品の著作権。 デフォルト値: 'Copyright.........' + "copyright": "", + // アプリケーションの説明。 デフォルト値: 'Built using Wails (https://wails.app)' + "comments": "" + }, + // 'multiple': アーキテクチャごとに1つのインストーラ。 'single': ビルドした全アーキテクチャに対応する単一ユニバーサルインストーラ。 デフォルト値: 'multiple' + "nsisType": "", + // アプリ難読化を実行するかどうか。 デフォルト値: false + "obfuscated": "", + // obfuscatedフラグがtrueの際に、garbleコマンドへ渡す引数。 + "garbleargs": "" +} +``` + +このファイルは、Wails CLIで `wails build` コマンドまたは `wails dev` コマンドを実行した際に読み込まれます。 + +`wails build/dev` コマンドを実行時に、`assetdir`、`reloaddirs`、`wailsjsdir`、`debounceMS`、`devserver`、`frontenddevserverurl`フラグを使用すると、プロジェクト構成が更新され、次回以降コマンドを実行する際のデフォルト値となります。 + +このファイルのJSONスキーマは、[こちら](https://wails.io/schemas/config.v2.json)にあります。 diff --git a/website/versioned_docs/version-v2.6.0/reference/runtime/_category_.json b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/_category_.json similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/runtime/_category_.json rename to website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/_category_.json diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx new file mode 100644 index 00000000000..9e146a3da00 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx @@ -0,0 +1,13 @@ +--- +sidebar_position: 7 +--- + +# ブラウザ + +これらは、システムブラウザに関連したメソッドです。 + +### BrowserOpenURL + +指定されたURLをシステムブラウザで開きます。 + +Go: `BrowserOpenURL(ctx context.Context, url string)`
JS: `BrowserOpenURL(url string)` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx new file mode 100644 index 00000000000..9e632294ba2 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx @@ -0,0 +1,23 @@ +--- +sidebar_position: 8 +--- + +# クリップボード + +ランタイム機能の一部として、オペレーティングシステムのクリップボードへのアクセスを提供します。
現在は、テキストの処理のみに対応しています。 + +### ClipboardGetText + +このメソッドは、クリップボードに現在保存されているテキストを読み込みます。 + +Go: `ClipboardGetText(ctx context.Context) (string, error)`
返り値: 文字列(クリップボードが空の場合は、空文字)またはエラー。 + +JS: `ClipboardGetText(): Promise`
返り値: 文字列を待機するPromise(クリップボードが空の場合は、空文字)。 + +### ClipboardSetText + +このメソッドは、クリップボードにテキストを書き込みます。 + +Go: `ClipboardSetText(ctx context.Context, text string) error`
返り値: anyの場合はエラー。 + +JS: `ClipboardSetText(text: string): Promise`
返り値: クリップボードにテキストが正常に書き込まれた場合はtrue、そうでない場合はfalseを返すようなPromise。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx new file mode 100644 index 00000000000..721ba5f31d4 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx @@ -0,0 +1,302 @@ +--- +sidebar_position: 5 +--- + +# ダイアログ + +ランタイムでは、ファイルセレクターやメッセージボックスといったネイティブダイアログへのアクセスを提供しています。 + +:::info JavaScript + +現在、Javascriptランタイムではダイアログをサポートしていません。 + +::: + +### OpenDirectoryDialog + +ユーザにディレクトリの選択を求めるダイアログを開きます。 [OpenDialogOptions](#opendialogoptions)を使用してカスタマイズできます。 + +Go: `OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)` + +返り値: 選択されたディレクトリ(キャンセルされた場合は空) またはエラー + +### OpenFileDialog + +ユーザにファイルの選択を求めるダイアログを開きます。 [OpenDialogOptions](#opendialogoptions)を使用してカスタマイズできます。 + +Go: `OpenFileDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)` + +返り値: 選択されたファイル(キャンセルされた場合は空) またはエラー + +### OpenMultipleFilesDialog + +ユーザに複数ファイルの選択を求めるダイアログを開きます。 [OpenDialogOptions](#opendialogoptions)を使用してカスタマイズできます。 + +Go: `OpenMultipleFilesDialog(ctx context.Context, dialogOptions OpenDialogOptions) ([]string, error)` + +返り値: 選択された複数ファイル(キャンセルされた場合はnil) またはエラー + +### SaveFileDialog + +保存の目的でユーザにファイル名を入力選択させるダイアログを開きます。 [SaveDialogOptions](#savedialogoptions)を使用してカスタマイズできます。 + +Go: `SaveFileDialog(ctx context.Context, dialogOptions SaveDialogOptions) (string, error)` + +返り値: 入力選択されたファイル(キャンセルされた場合は空) またはエラー + +### MessageDialog + +メッセージダイアログを使用してメッセージを表示します。 [MessageDialogOptions](#messagedialogoptions)を使用してカスタマイズできます。 + +Go: `MessageDialog(ctx context.Context, dialogOptions MessageDialogOptions) (string, error)` + +返り値: 選択されたボタンのテキストまたはエラー + +## オプション + +### OpenDialogOptions + +```go +type OpenDialogOptions struct { + DefaultDirectory string + DefaultFilename string + Title string + Filters []FileFilter + ShowHiddenFiles bool + CanCreateDirectories bool + ResolvesAliases bool + TreatPackagesAsDirectories bool +} +``` + +| フィールド | 説明 | Win | Mac | Lin | +| -------------------------- | ------------------------- | --- | --- | --- | +| DefaultDirectory | ダイアログが開かれたときに初期表示するディレクトリ | ✅ | ✅ | ✅ | +| DefaultFilename | デフォルトファイル名 | ✅ | ✅ | ✅ | +| Title | ダイアログのタイトル | ✅ | ✅ | ✅ | +| [Filters](#filefilter) | ファイルフィルタのリスト | ✅ | ✅ | ✅ | +| ShowHiddenFiles | システムの隠しファイルを表示 | | ✅ | ✅ | +| CanCreateDirectories | ユーザによるディレクトリの作成を許可する | | ✅ | | +| ResolvesAliases | エイリアスではなくファイルパスを返す | | ✅ | | +| TreatPackagesAsDirectories | パッケージへのナビゲーションを許可 | | ✅ | | + +### SaveDialogOptions + +```go +type SaveDialogOptions struct { + DefaultDirectory string + DefaultFilename string + Title string + Filters []FileFilter + ShowHiddenFiles bool + CanCreateDirectories bool + TreatPackagesAsDirectories bool +} +``` + +| フィールド | 説明 | Win | Mac | Lin | +| -------------------------- | ------------------------- | --- | --- | --- | +| DefaultDirectory | ダイアログが開かれたときに初期表示するディレクトリ | ✅ | ✅ | ✅ | +| DefaultFilename | デフォルトファイル名 | ✅ | ✅ | ✅ | +| Title | ダイアログのタイトル | ✅ | ✅ | ✅ | +| [Filters](#filefilter) | ファイルフィルタのリスト | ✅ | ✅ | ✅ | +| ShowHiddenFiles | システムの隠しファイルを表示 | | ✅ | ✅ | +| CanCreateDirectories | ユーザによるディレクトリの作成を許可する | | ✅ | | +| TreatPackagesAsDirectories | パッケージへのナビゲーションを許可 | | ✅ | | + +### MessageDialogOptions + +```go +type MessageDialogOptions struct { + Type DialogType + Title string + Message string + Buttons []string + DefaultButton string + CancelButton string +} +``` + +| フィールド | 説明 | Win | Mac | Lin | +| ------------- | ------------------------------------------------- | -------------- | --- | --- | +| Type | メッセージダイアログの種類 (質問、情報など) | ✅ | ✅ | ✅ | +| Title | ダイアログのタイトル | ✅ | ✅ | ✅ | +| Message | ユーザに表示するメッセージ | ✅ | ✅ | ✅ | +| Buttons | ボタンテキストのリスト | | ✅ | | +| DefaultButton | 指定されたテキストのボタンをデフォルトボタンとして扱う。 `return`キーにバインドされます。 | ✅[*](#windows) | ✅ | | +| CancelButton | 指定されたテキストのボタンをキャンセルボタンとして扱う。 `escape`キーにバインドされます。 | | ✅ | | + +#### Windows + +Windowsでは、ボタンのカスタマイズができない標準ダイアログタイプがあります。 返却される値は次のいずれかとなります: "Ok"、"Cancel"、"Abort"、"Retry"、"Ignore"、"Yes"、"No"、"Try Again"、"Continue"。 + +質問ダイアログの場合、デフォルトボタンは"Yes"、キャンセルボタンは"No"となります。 この設定は、`DefaultButton`の値を`"No"`にすることで、変更できます。 + +例: +```go + result, err := runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Question", + Message: "Do you want to continue?", + DefaultButton: "No", + }) +``` + +#### Linux + +Linuxでは、ボタンのカスタマイズができない標準ダイアログタイプがあります。 返り値は次のいずれかになります: "Ok"、"Cancel"、"Yes"、"No" + +#### Mac + +Macのメッセージダイアログでは、最大4つまでのボタンを指定できます。 `DefaultButton`や`CancelButton`が指定されていない場合、1番目のボタンがデフォルトボタンとして扱われ、`return`キーにバインドされます。 + +例えば次のようなコードの場合: + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, +}) +``` + +1番目のボタンがデフォルトになります: + +```mdx-code-block +
+ +
+
+``` + +そして`DefaultButton`を"two"に設定した場合: + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, + DefaultButton: "two", +}) +``` + +2番目のボタンがデフォルトになります。 このとき`return`キーが押されると、返り値として"two"が返却されます: + +```mdx-code-block +
+ +
+
+``` + +また、`CancelButton`を"three"に設定した場合 + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, + DefaultButton: "two", + CancelButton: "three", +}) +``` + +ダイアログの下部に"three"ボタンが表示されるようになります。 このとき`escape`キーが押されると、返り値として"three"が返却されます: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### DialogType + +```go +const ( + InfoDialog DialogType = "info" + WarningDialog DialogType = "warning" + ErrorDialog DialogType = "error" + QuestionDialog DialogType = "question" + ) +``` + +### FileFilter + +```go +type FileFilter struct { + DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)" + Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png" +} +``` + +#### Windows + +Windowsでは、ダイアログボックスで複数のファイルフィルタを使用できます。 それぞれのFileFiltersは、ダイアログ上で個別のエントリーとして表示されます: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### Linux + +Linuxでは、ダイアログボックスで複数のファイルフィルタを使用できます。 それぞれのFileFiltersは、ダイアログ上で個別のエントリーとして表示されます: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### Mac + +Macのダイアログでは、ファイルをフィルタするためのパターンセットは1つしか持たせることができません。 もし複数のFileFiltersを定義した場合、Wailsはそれらすべてのパターンを使用します。 + +例: + +```go + selection, err := runtime.OpenFileDialog(b.ctx, runtime.OpenDialogOptions{ + Title: "Select File", + Filters: []runtime.FileFilter{ + { + DisplayName: "Images (*.png;*.jpg)", + Pattern: "*.png;*.jpg", + }, { + DisplayName: "Videos (*.mov;*.mp4)", + Pattern: "*.mov;*.mp4", + }, + }, + }) +``` + +このとき、ファイル選択ダイアログを開くと、`*.png,*.jpg,*.mov,*.mp4`がフィルタとして使用されます。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx new file mode 100644 index 00000000000..ac4f40eba00 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx @@ -0,0 +1,37 @@ +--- +sidebar_position: 2 +--- + +# イベント + +Wailsでは、GoまたはJavaScriptによって発行および受信できる、一元化されたイベントシステムが用意されています。 必要に応じて、イベント発行時にデータを渡すことも可能です。 イベントリスナーは、そのデータをローカルデータ型で受け取ります。 + +### EventsOn + +このメソッドは、指定されたイベント名のイベントリスナーを新たに設定します。 `eventName`という名前のイベントが[発行](#EventsEmit)されると、コールバックがトリガーされます。 イベント発行時にデータも付与されていた場合、そのデータはコールバックに渡されます。 このメソッドは、リスナーをキャンセルするための関数を返します。 + +Go: `EventsOn(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`
JS: `EventsOn(eventName string, callback function(optionalData?: any)): () => void` + +### EventsOff + +このメソッドは、指定されたイベント名のイベントリスナー設定を解除します。引数の`additionalEventNames`を使用することで、複数のリスナーを一度に解除できます。 + +Go: `EventsOff(ctx context.Context, eventName string, additionalEventNames ...string)`
JS: `EventsOff(eventName string, ...additionalEventNames)` + +### EventsOnce + +このメソッドは、指定されたイベント名のイベントリスナーを新たに設定し、一度だけトリガーさせます。 このメソッドは、リスナーをキャンセルするための関数を返します。 + +Go: `EventsOnce(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`
JS: `EventsOnce(eventName string, callback function(optionalData?: any)): () => void` + +### EventsOnMultiple + +このメソッドは、指定されたイベント名のイベントリスナーを新たに設定し、最大`counter`回だけトリガーします。 このメソッドは、リスナーをキャンセルするための関数を返します。 + +Go: `EventsOnMultiple(ctx context.Context, eventName string, callback func(optionalData ...interface{}), counter int) func()`
JS: `EventsOnMultiple(eventName string, callback function(optionalData?: any), counter int): () => void` + +### EventsEmit + +このメソッドは、指定されたイベントを発行します。 必要に応じて、イベント発行時にデータを渡すこともできます。 このメソッドによって、任意のイベントリスナーをトリガーさせることができます。 + +Go: `EventsEmit(ctx context.Context, eventName string, optionalData ...interface{})`
JS: `EventsEmit(eventName: string, ...optionalData: any)` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx new file mode 100644 index 00000000000..01e62ff1af0 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx @@ -0,0 +1,85 @@ +--- +sidebar_position: 1 +--- + +# イントロダクション + +ランタイムは、アプリケーションにユーティリティメソッドを提供するライブラリです。 GoとJavaScriptの両方にランタイムがあり、どちらにもほぼ同じメソッドが提供されています。 + +ユーティリティメソッドには次のようなものがあります: + +- [ウィンドウ](window.mdx) +- [メニュー](menu.mdx) +- [ダイアログ](dialog.mdx) +- [イベント](events.mdx) +- [ブラウザ](browser.mdx) +- [ログ](log.mdx) +- [クリップボード](clipboard.mdx) + +Goのランタイムは、`github.com/wailsapp/wails/v2/pkg/runtime`をインポートすることで利用できます。 このパッケージのすべてのメソッドは、1番目の引数でContextを渡す必要があります。 このContextは、[OnStartup](../options.mdx#onstartup)フック、または[OnDomReady](../options.mdx#ondomready)フックからあらかじめ取得しておいてください。 + +:::info 備考 + +[OnStartup](../options.mdx#onstartup)で提供されるContextは、ウィンドウが別のスレッドで初期化されているため、ランタイムが機能する保証がありません。 起動時にランタイムメソッドを呼び出したい場合は、[OnDomReady](../options.mdx#ondomready)を使用してください。 + +::: + +JavaScriptのランタイムは、`window.runtime`マップを介してフロントエンド上で利用できます。 `dev`モードでは、TypeScript型定義を提供するランタイムパッケージが生成されます。 これらは、フロントエンドディレクトリの`wailsjs`ディレクトリに配置しておく必要があります。 + +### Hide + +Go: `Hide(ctx context.Context)`
JS: `Hide()` + +アプリケーションを非表示にします。 + +:::info 備考 + +Macでこのメソッドを使用すると、標準のMacアプリケーションにおけるメニュー項目の`Hide`と同じ方法で、アプリケーションが非表示になります。 これはウィンドウの非表示とは異なりますが、アプリケーションはフォアグラウンドに残ったままになります。 WindowsおよびLinuxでは、`WindowHide`メソッドと同等です。 + +::: + +### Show + +アプリケーションを表示します。 + +:::info 備考 + +Macでこのメソッドを使用すると、アプリケーションがフォアグラウンドに戻ります。 WindowsおよびLinuxでは、`WindowShow`メソッドと同等です。 + +::: + +Go: `Show(ctx context.Context)`
JS: `Show()` + +### Quit + +アプリケーションを終了します。 + +Go: `Quit(ctx context.Context)`
JS: `Quit()` + +### Environment + +現在の環境の詳細情報を取得します。 + +Go: `Environment(ctx context.Context) EnvironmentInfo`
JS: `Environment(): Promise` + +#### EnvironmentInfo + +Go: + +```go +type EnvironmentInfo struct { + BuildType string + Platform string + Arch string +} +``` + +JS: + +```ts +interface EnvironmentInfo { + buildType: string; + platform: string; + arch: string; +} +``` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx new file mode 100644 index 00000000000..924f6257ac1 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 3 +--- + +# ログ + +Wailsでは、GoまたはJavaScriptから呼び出すことのできるロギングメカニズムを用意しています。 一般的なロガーと同じように、ログにはいくつかのログレベルがあります: + +- Trace +- Debug +- Info +- Warning +- Error +- Fatal + +ロガーは、設定されている出力ログレベル以上のログメッセージを出力します。 例えば、出力ログレベルを`Debug`に設定した場合、`Trace`以外のすべてのレベルのメッセージが出力されます。 + +### LogPrint + +指定されたメッセージをRawメッセージとしてロギングします。 + +Go: `LogPrint(ctx context.Context, message string)`
JS: `LogPrint(message: string)` + +### LogPrintf + +指定されたメッセージをRawメッセージとしてロギングします。 + +Go: `LogPrintf(ctx context.Context, format string, args ...interface{})`
+ +### LogTrace + +指定されたメッセージを`Trace`ログレベルでロギングします。 + +Go: `LogTrace(ctx context.Context, message string)`
JS: `LogTrace(message: string)` + +### LogTracef + +指定されたメッセージを`Trace`ログレベルでロギングします。 + +Go: `LogTracef(ctx context.Context, format string, args ...interface{})`
+ +### LogDebug + +指定されたメッセージを`Debug`ログレベルでロギングします。 + +Go: `LogDebug(ctx context.Context, message string)`
JS: `LogDebug(message: string)` + +### LogDebugf + +指定されたメッセージを`Debug`ログレベルでロギングします。 + +Go: `LogDebugf(ctx context.Context, format string, args ...interface{})`
+ +### LogInfo + +指定されたメッセージを`Info`ログレベルでロギングします。 + +Go: `LogInfo(ctx context.Context, message string)`
JS: `LogInfo(message: string)` + +### LogInfof + +指定されたメッセージを`Info`ログレベルでロギングします。 + +Go: `LogInfof(ctx context.Context, format string, args ...interface{})`
+ +### LogWarning + +指定されたメッセージを`Warning`ログレベルでロギングします。 + +Go: `LogWarning(ctx context.Context, message string)`
JS: `LogWarning(message: string)` + +### LogWarningf + +指定されたメッセージを`Warning`ログレベルでロギングします。 + +Go: `LogWarningf(ctx context.Context, format string, args ...interface{})`
+ +### LogError + +指定されたメッセージを`Error`ログレベルでロギングします。 + +Go: `LogError(ctx context.Context, message string)`
JS: `LogError(message: string)` + +### LogErrorf + +指定されたメッセージを`Error`ログレベルでロギングします。 + +Go: `LogErrorf(ctx context.Context, format string, args ...interface{})`
+ +### LogFatal + +指定されたメッセージを`Fatal`ログレベルでロギングします。 + +Go: `LogFatal(ctx context.Context, message string)`
JS: `LogFatal(message: string)` + +### LogFatalf + +指定されたメッセージを`Fatal`ログレベルでロギングします。 + +Go: `LogFatalf(ctx context.Context, format string, args ...interface{})`
+ +### LogSetLogLevel + +出力ログレベルを設定します。 JavaScriptでは、数値が次のログレベルに対応しています: + +| 値 | ログレベル | +| - | ------- | +| 1 | Trace | +| 2 | Debug | +| 3 | Info | +| 4 | Warning | +| 5 | Error | + +Go: `LogSetLogLevel(ctx context.Context, level logger.LogLevel)`
JS: `LogSetLogLevel(level: number)` + +## カスタムロガーの使用 + +カスタムロガーは、アプリケーションオプションの1つである[Logger](../options.mdx#logger)で指定してあげることで、使用することができます。 カスタムロガーを使用する際の唯一の要件は、`github.com/wailsapp/wails/v2/pkg/logger`で定義されている`logger.Logger`インターフェースを、ロガーに実装することです: + +```go title="logger.go" +type Logger interface { + Print(message string) + Trace(message string) + Debug(message string) + Info(message string) + Warning(message string) + Error(message string) + Fatal(message string) +} +``` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx new file mode 100644 index 00000000000..9d38fcd62a7 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx @@ -0,0 +1,25 @@ +--- +sidebar_position: 6 +--- + +# メニュー + +これらは、アプリケーションメニューに関連したメソッドです。 + +:::info JavaScript + +現在、Javascriptランタイムではメニューをサポートしていません。 + +::: + +### MenuSetApplicationMenu + +指定された[menu](../menus.mdx)をアプリケーションメニューとして設定します。 + +Go: `MenuSetApplicationMenu(ctx context.Context, menu *menu.Menu)` + +### MenuUpdateApplicationMenu + +`MenuSetApplicationMenu`に渡されたメニューへの変更を検知し、アプリケーションメニューを更新します。 + +Go: `MenuUpdateApplicationMenu(ctx context.Context)` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx new file mode 100644 index 00000000000..954c407d5ca --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx @@ -0,0 +1,38 @@ +--- +sidebar_position: 9 +--- + +# スクリーン + +これらのメソッドは、現在接続されているスクリーンに関する情報を提供します。 + +### ScreenGetAll + +現在接続されているスクリーンのリストを返します。 + +Go: `ScreenGetAll(ctx context.Context) []screen`
+JS: `ScreenGetAll()` + +#### スクリーン + +Go構造体: + +```go +type Screen struct { + IsCurrent bool + IsPrimary bool + Width int + Height int +} +``` + +Typescript型定義: + +```ts +interface Screen { + isCurrent: boolean; + isPrimary: boolean; + width : number + height : number +} +``` diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx new file mode 100644 index 00000000000..ea6dd358d5b --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx @@ -0,0 +1,227 @@ +--- +sidebar_position: 4 +--- + +# ウィンドウ + +アプリケーションウィンドウを制御できるメソッド群です。 + +### WindowSetTitle + +ウィンドウのタイトルバーにテキストを設定します。 + +Go: `WindowSetTitle(ctx context.Context, title string)`
JS: `WindowSetTitle(title: string)` + +### WindowFullscreen + +ウィンドウをフルスクリーンにします。 + +Go: `WindowFullscreen(ctx context.Context)`
JS: `WindowFullscreen()` + +### WindowUnfullscreen + +フルスクリーンにする前のウィンドウサイズおよび位置に戻します。 + +Go: `WindowUnfullscreen(ctx context.Context)`
JS: `WindowUnfullscreen()` + +### WindowIsFullscreen + +ウィンドウがフルスクリーンの場合は、trueを返します。 + +Go: `WindowIsFullscreen(ctx context.Context) bool`
JS: `WindowIsFullscreen() bool` + +### WindowCenter + +ウィンドウが現在表示されているモニターの中央に、ウィンドウを配置させます。 + +Go: `WindowCenter(ctx context.Context)`
JS: `WindowCenter()` + +### WindowExecJS + +ウィンドウ内で、任意のJSコードを実行します。 + +このメソッドは、ブラウザ上で非同期にコードを実行し、すぐにリターンされます。 スクリプトでエラーが発生した場合、エラーログはブラウザコンソールでのみ確認できます。 + +Go: `WindowExecJS(ctx context.Context, js string)` + +### WindowReload + +リロードします。(現在表示されているページをリロード) + +Go: `WindowReload(ctx context.Context)`
JS: `WindowReload()` + +### WindowReloadApp + +アプリケーションフロントエンドをリロードします。 + +Go: `WindowReloadApp(ctx context.Context)`
JS: `WindowReloadApp()` + +### WindowSetSystemDefaultTheme + +Windowsのみ使用可能。 + +Go: `WindowSetSystemDefaultTheme(ctx context.Context)`
JS: `WindowSetSystemDefaultTheme()` + +ウィンドウのテーマをシステムデフォルト(ダーク/ライト) に設定します。 + +### WindowSetLightTheme + +Windowsのみ使用可能。 + +Go: `WindowSetLightTheme(ctx context.Context)`
JS: `WindowSetLightTheme()` + +ウィンドウのテーマをライトに設定します。 + +### WindowSetDarkTheme + +Windowsのみ使用可能。 + +Go: `WindowSetDarkTheme(ctx context.Context)`
JS: `WindowSetDarkTheme()` + +ウィンドウのテーマをダークに設定します。 + +### WindowShow + +ウィンドウが非表示になっている場合は、表示させます。 + +Go: `WindowShow(ctx context.Context)`
JS: `WindowShow()` + +### WindowHide + +現在表示されているウィンドウを非表示にします。 + +Go: `WindowHide(ctx context.Context)`
JS: `WindowHide()` + +### WindowIsNormal + +ウィンドウが最小化、最大化、またはフルスクリーンになっていない場合、trueを返します。 + +Go: `WindowIsNormal(ctx context.Context) bool`
JS: `WindowIsNormal() bool` + +### WindowSetSize + +ウィンドウの幅と高さを設定します。 + +Go: `WindowSetSize(ctx context.Context, width int, height int)`
JS: `WindowSetSize(width: number, height: number)` + +### WindowGetSize + +ウィンドウの幅と高さを取得します。 + +Go: `WindowGetSize(ctx context.Context) (width int, height int)`
JS: `WindowGetSize() : Size` + +### WindowSetMinSize + +ウィンドウの最小サイズを設定します。 現在のウィンドウサイズが、指定された最小サイズよりも小さい場合、現在のウィンドウサイズは変更されます。 + +サイズを`0,0`に設定すると、サイズの制約が無効化されます。 + +Go: `WindowSetMinSize(ctx context.Context, width int, height int)`
JS: `WindowSetMinSize(width: number, height: number)` + +### WindowSetMaxSize + +ウィンドウの最大サイズを設定します。 現在のウィンドウサイズが、指定された最大サイズよりも大きい場合、現在のウィンドウサイズは変更されます。 + +サイズを`0,0`に設定すると、サイズの制約が無効化されます。 + +Go: `WindowSetMaxSize(ctx context.Context, width int, height int)`
JS: `WindowSetMaxSize(width: number, height: number)` + +### WindowSetAlwaysOnTop + +ウィンドウを常に最前面に表示するかを切り替えます。 + +Go: `WindowSetAlwaysOnTop(ctx context.Context, b bool)`
JS: `WindowSetAlwaysOnTop(b: Boolen)` + +### WindowSetPosition + +現在ウィンドウが表示されているモニターに対する、相対的なウィンドウ位置を設定します。 + +Go: `WindowSetPosition(ctx context.Context, x int, y int)`
JS: `WindowSetPosition(x: number, y: number)` + +### WindowGetPosition + +現在ウィンドウが表示されているモニターに対する、相対的なウィンドウ位置を取得します。 + +Go: `WindowGetPosition(ctx context.Context) (x int, y int)`
JS: `WindowGetPosition() : Position` + +### WindowMaximise + +ウィンドウを最大化します。 + +Go: `WindowMaximise(ctx context.Context)`
JS: `WindowMaximise()` + +### WindowUnmaximise + +ウィンドウの最大化を解除し、最大化する前のサイズおよび位置に戻します。 + +Go: `WindowUnmaximise(ctx context.Context)`
JS: `WindowUnmaximise()` + +### WindowIsMaximised + +ウィンドウが最大化している場合はtrueを返します。 + +Go: `WindowIsMaximised(ctx context.Context) bool`
JS: `WindowIsMaximised() bool` + +### WindowToggleMaximise + +最大化の状態を切り替えます。 + +Go: `WindowToggleMaximise(ctx context.Context)`
JS: `WindowToggleMaximise()` + +### WindowMinimise + +ウィンドウを最小化します。 + +Go: `WindowMinimise(ctx context.Context)`
JS: `WindowMinimise()` + +### WindowUnminimise + +ウィンドウの最小化を解除し、最小化する前のサイズおよび位置に戻します。 + +Go: `WindowUnminimise(ctx context.Context)`
JS: `WindowUnminimise()` + +### WindowIsMinimised + +ウィンドウが最小化している場合はtrueを返します。 + +Go: `WindowIsMinimised(ctx context.Context) bool`
JS: `WindowIsMinimised() bool` + +### WindowSetBackgroundColour + +ウィンドウの背景色をRGBAカラー定義で設定します。 この色は、すべての透過ピクセルに対して表示されます。 + +R、G、B、Aの有効な値の範囲は0~255です。 + +:::info Windows + +Windowsの場合、0または255のアルファ値(A) のみがサポートされています。 0以外の値を指定すると、すべて255とみなされます。 + +::: + +Go: `WindowSetBackgroundColour(ctx context.Context, R, G, B, A uint8)`
JS: `WindowSetBackgroundColour(R, G, B, A)` + +### WindowPrint + +ネイティブな印刷ダイアログを開きます。 + +Go: `WindowPrint(ctx context.Context)`
JS: `WindowPrint()` + +## TypeScript型定義 + +### Position + +```ts +interface Position { + x: number; + y: number; +} +``` + +### Size + +```ts +interface Size { + w: number; + h: number; +} +``` diff --git a/website/versioned_docs/version-v2.6.0/tutorials/_category_.json b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/_category_.json similarity index 100% rename from website/versioned_docs/version-v2.6.0/tutorials/_category_.json rename to website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/_category_.json diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx new file mode 100644 index 00000000000..8422c83f715 --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx @@ -0,0 +1,245 @@ +--- +sidebar_position: 20 +--- + +# ドッグAPI + +```mdx-code-block +
+ +
+
+``` + +:::note + +このチュートリアルは[@tatadan](https://twitter.com/tatadan)より提供されたもので、[Wails Examples Repository](https://github.com/tataDan/wails-v2-examples)の一部になります。 + +::: + +このチュートリアルでは、Webから犬の写真を取得して表示するためのアプリケーションを開発していきます。 + +### プロジェクトの作成 + +アプリケーションを作成していきましょう。 ターミナルで次のように入力します: `wails init -n dogs-api -t svelte` + +注意: IDEサポートが欲しい場合は、コマンドの末尾に、`-ide vscode`オプションまたは`-ide goland`オプションを付与してください。 + +では、`cd dogs-api`で移動し、プロジェクトファイルの編集を始めましょう。 + +### 未使用コードの削除 + +まず、使用しないと分かっているいくつかの要素を削除していきます: + +- `app.go`を開き、次の行を削除します: + +```go +// Greet returns a greeting for the given name +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s, It's show time!", name) +} +``` + +- `frontend/src/App.svelte`を開き、すべての行を削除します。 +- `frontend/src/assets/images/logo-universal.png`ファイルを削除します。 + +### アプリケーションの作成 + +では、新しいGoコードを書いていきましょう。 + +関数を定義する前に、`app.go`に下記の構造体の宣言を追加します: + +```go +type RandomImage struct { + Message string + Status string +} + +type AllBreeds struct { + Message map[string]map[string][]string + Status string +} + +type ImagesByBreed struct { + Message []string + Status string +} +``` + +下記の関数を`app.go`に追加します(おそらく既存の関数定義の後ろ側に追加することになります): + +```go +func (a *App) GetRandomImageUrl() string { + response, err := http.Get("https://dog.ceo/api/breeds/image/random") + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data RandomImage + json.Unmarshal(responseData, &data) + + return data.Message +} + +func (a *App) GetBreedList() []string { + var breeds []string + + response, err := http.Get("https://dog.ceo/api/breeds/list/all") + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data AllBreeds + json.Unmarshal(responseData, &data) + + for k := range data.Message { + breeds = append(breeds, k) + } + + sort.Strings(breeds) + + return breeds +} + +func (a *App) GetImageUrlsByBreed(breed string) []string { + + url := fmt.Sprintf("%s%s%s%s", "https://dog.ceo/api/", "breed/", breed, "/images") + response, err := http.Get(url) + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data ImagesByBreed + json.Unmarshal(responseData, &data) + + return data.Message +} +``` + +`app.go`の`import`セクションを次のように変更します: + +```go +import ( + "context" + "fmt" + "encoding/json" + "io/ioutil" + "log" + "net/http" + "sort" +) +``` + +`frontend/src/App.svelte`に次の行を追加します: + + +```html + + +

Dogs API

+
+ + Click on down arrow to select a breed + + +
+
+{#if showRandomPhoto} + No dog found +{/if} +{#if showBreedPhotos} + {#each photos as photo} + No dog found + {/each} +{/if} + + +``` + + +### アプリケーションのテスト + +バインディングを生成してアプリケーションをテストするには、`wails dev`コマンドを実行してください。 + +### アプリケーションのコンパイル + +アプリケーションを本番用の単一バイナリにコンパイルするには、`wails build`コマンドを実行してください。 diff --git a/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx new file mode 100644 index 00000000000..55c52342d7b --- /dev/null +++ b/website/i18n/ja/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx @@ -0,0 +1,123 @@ +--- +sidebar_position: 10 +--- + +# Hello World + +このチュートリアルの目的は、Wailsを使用して、最も基礎的なアプリケーションを起動および実行することです。 あなたは、次のことができるようになります: + +- 新しいWailsアプリケーションを作成する +- アプリケーションをビルドする +- アプリケーションを実行する + +:::note + +このチュートリアルでは、Windowsをターゲットプラットフォームとして使用します。 出力される内容は、オペレーティングシステムによって多少異なります。 + +::: + +## 新しいWailsアプリケーションを作成する + +デフォルトのバニラJSテンプレートを使用して、新しいWailsアプリケーションを作成するには、次のコマンドを実行します: + +```bash +wails init -n helloworld +``` + +すると、次のように表示されます: + +``` +Wails CLI v2.0.0 + +Initialising Project 'helloworld' +--------------------------------- + +Project Name: helloworld +Project Directory: C:\Users\leaan\tutorial\helloworld +Project Template: vanilla +Template Support: https://wails.io + +Initialised project 'helloworld' in 232ms. +``` + +これにより、カレントディレクトリに`helloworld`という新しいディレクトリが作成されます。 このディレクトリには、いくつかのファイルがあります: + +``` +build/ - Contains the build files + compiled application +frontend/ - Contains the frontend files +app.go - Contains the application code +main.go - The main program with the application configuration +wails.json - The project configuration file +go.mod - The go module file +go.sum - The go module checksum file +``` + +## アプリケーションをビルドする + +アプリケーションをビルドするには、新しくできた`helloworld`プロジェクトディレクトリに移動し、次のコマンドを実行します: + +```bash +wails build +``` + +すると、次のように表示されます: + +``` +Wails CLI v2.0.0 + +App Type: desktop +Platforms: windows/amd64 +Compiler: C:\Users\leaan\go\go1.18.3\bin\go.exe +Build Mode: Production +Devtools: false +Skip Frontend: false +Compress: false +Package: true +Clean Build Dir: false +LDFlags: "" +Tags: [] +Race Detector: false + +Building target: windows/amd64 +------------------------------ + - Installing frontend dependencies: Done. + - Compiling frontend: Done. + - Generating bundle assets: Done. + - Compiling application: Done. +Built 'C:\Users\leaan\tutorial\helloworld\build\bin\helloworld.exe' in 10.616s. +``` + +これにより、アプリケーションがコンパイルされ、`build/bin`ディレクトリに保存されます。 + +## アプリケーションを実行する + +Windowsのエクスプローラで`build/bin`ディレクトリを閲覧すると、プロジェクトのバイナリファイルが存在するはずです: + +```mdx-code-block +
+ +
+
+``` + +`helloworld.exe`ファイルをダブルクリックするだけで起動できます。 + +Macの場合、Wailsは`helloworld.app`ファイルを生成します。このファイルをダブルクリックすることで起動できます。 + +Linuxの場合、`build/bin`ディレクトリ内の`./helloworld`を呼び出すことでアプリケーションを起動できます。 + +アプリケーションが期待したとおりに動作することでしょう: + +```mdx-code-block +
+ +
+
+``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx new file mode 100644 index 00000000000..e36a6edfe8c --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 2 +--- + +# Links + +This page serves as a list for community related links. Please submit a PR (click `Edit this page` at the bottom) to submit links. + +## Awesome Wails + +The [definitive list](https://github.com/wailsapp/awesome-wails) of links related to Wails. + +## Support Channels + +- [Wails Discord Server](https://discord.gg/JDdSxwjhGf) +- [Github Issues](https://github.com/wailsapp/wails/issues) +- [v2 Beta Discussion Board](https://github.com/wailsapp/wails/discussions/828) + +## Social Media + +- [Twitter](https://twitter.com/wailsapp) +- [Wails Chinese Community QQ Group](https://qm.qq.com/cgi-bin/qm/qr?k=PmIURne5hFGNd7QWzW5qd6FV-INEjNJv&jump_from=webapi) - Group number: 1067173054 + +## Other Tutorials and Articles + +- [Building of Bulletin Board](https://blog.customct.com/building-bulletin-board) diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/bulletinboard.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/bulletinboard.mdx rename to website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..9d2a86918ba --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx @@ -0,0 +1,39 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN 추적기](https://github.com/williamsjokvist/cfn-tracker) - Street Fighter 6 +또는 V CFN 프로필의 실시간 경기를 추적하세요. 시작하려면 +[웹사이트](https://cfn.williamsjokvist.se/)를 확인하세요. + +## 특징 + +- 실시간 경기 추적 +- 경기 로그 및 통계 저장 +- 브라우저 소스를 통해 OBS에 실시간 통계 표시 지원 +- SF6 및 SFV 모두 지원 +- 사용자가 CSS를 사용하여 자신만의 OBS 브라우저 테마를 만들 수 있는 기능 + +### 웨일스와 함께 사용되는 주요 기술 + +- [작업](https://github.com/go-task/task) - 일반적인 명령을 쉽게 사용할 수 있도 + 록 Wails CLI를 래핑합니다. +- [React](https://github.com/facebook/react) - 풍부한 생태계(radix, 프레이머-모 + 션)로 인해 선택됨 +- [Bun](https://github.com/oven-sh/bun) - 빠른 종속성 해결 및 빌드 시간에 사용됩 + 니다. +- [Rod](https://github.com/go-rod/rod) - 인증 및 폴링 변경을 위한 헤드리스 브라 + 우저 자동화 +- [SQLite](https://github.com/mattn/go-sqlite3) - 경기, 세션 및 프로필을 저장하 + 는 데 사용됩니다. +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + OBS 브라우저 소스에 추적 업데이트를 보내는 http 스트림 +- [i18next](https://github.com/i18next/) - Go 레이어에서 현지화 개체를 제공하기 + 위한 백엔드 커넥터 포함 +- [xstate](https://github.com/statelyai/xstate) - 인증 프로세스 및 추적을 위한 + 상태 머신 diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/emailit.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/emailit.mdx rename to website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx new file mode 100644 index 00000000000..4c8cac235a3 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx @@ -0,0 +1,12 @@ +# EncryptEasy + +```mdx-code-block +

+ +
+

+``` + +**[EncryptEasy](https://www.encrypteasy.app)는 간단하고 사용하기 쉬운 PGP 암호화 도구로 모든 키들을 관리합니다. 암호화는 간단해야 합니다. 그리고 Wails로 개발되었습니다.** + +PGP를 사용한 메시지 암호화는 업계 표준입니다. 모두 개인 키와 공개 키를 가지고 있습니다. 귀하의 개인 키는 귀하만 메시지를 읽을 수 있도록 비공개로 유지되어야 합니다. 귀하의 공개 키는 귀하에게 암호화된 비밀 메시지를 보내려는 모든 사람에게 배포됩니다. 키 관리, 메시지 암호화 및 메시지 해독은 매끄러운 경험이어야 합니다. EncryptEasy는 모든 것을 쉽게 만드는 것입니다. EncryptEasy는 모든 것을 쉽게 만듭니다. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx new file mode 100644 index 00000000000..73f93417cf0 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx @@ -0,0 +1,13 @@ +# ESP Studio + +```mdx-code-block +

+ +
+

+``` + +[ESP Studio](https://github.com/torabian/esp-studio) - 크로스 플랫폼, 데스크탑, 클라우드 및 임베디드 소프트웨어 +ESP/Arduino 장치 제어, 복잡한 IOT 워크플로 및 제어 시스템 구축용 \ No newline at end of file diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx new file mode 100644 index 00000000000..0881bfe9e1e --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx @@ -0,0 +1,16 @@ +# FileHound Export Utility + +```mdx-code-block +

+ +
+

+``` + +[FileHound Export Utility](https://www.filehound.co.uk/) FileHound는 안전한 파일 보존, 비즈니스 프로세스 자동화 및 SmartCapture 기능을 위해 만들어진 클라우드 문서 관리 플랫폼입니다. + +FileHound Export Utility를 사용하면 FileHound 관리자가 대체 백업 및 복구 목적으로 보안 문서 및 데이터 추출 작업을 실행할 수 있습니다. 이 응용 프로그램은 선택한 필터를 기반으로 FileHound에 저장된 모든 문서 및/또는 메타 데이터를 다운로드합니다. 메타데이터는 JSON 및 XML 형식으로 내보낼 수 있습니다. + +백엔드의 구성은 다음과 같습니다: Go 1.15 Wails 1.11.0 go-sqlite3 1.14.6 go-linq 3.2 + +사용된 프론트엔드: Vue 2.6.11 Vuex 3.4.0 TypeScript Tailwind 1.9.6 diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx new file mode 100644 index 00000000000..87e5837d32f --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx @@ -0,0 +1,10 @@ +# hiposter + +```mdx-code-block +

+ +
+

+``` + +[hiposter](https://github.com/obity/hiposter) is a simple and efficient http API testing client tool. Based on Wails, Go and sveltejs. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx new file mode 100644 index 00000000000..d31eac0d5f8 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx @@ -0,0 +1,14 @@ +# Minecraft Updater + +```mdx-code-block +

+ +
+

+``` + +[Minecraft Updater](https://github.com/Gurkengewuerz/MinecraftModUpdater)는 사용자 기반의 Minecraft 모드를 업데이트하고 동기화하는 유틸리티 도구입니다. Wails2와 [antd](https://ant.design/)를 프런트엔드 프레임워크로 사용한 React를 사용하여 구축되었습니다. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx new file mode 100644 index 00000000000..9c98dc86473 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx @@ -0,0 +1,14 @@ +# Modal File Manager + +```mdx-code-block +

+ +
+

+``` + +[Modal File Manager](https://github.com/raguay/ModalFileManager) 는 웹 기술을 사용하는 이중 창 모양의 파일 관리자입니다. 나의 원래 디자인은 NW.js를 기반으로 했으며 [여기](https://github.com/raguay/ModalFileManager-NWjs)에서 찾을 수 있습니다. 이 버전은 동일한 Svelte 기반 프론트엔드 코드를 사용하지만(그러나 NW.js에서 출발한 이후 크게 수정됨) 백엔드는 [Wails 2](https://wails.io/) 구현입니다. By using this implementation, I no longer use command line `rm`, `cp`, etc. commands, but a git install has to be on the system to download themes and extensions. Go를 사용하여 코딩되었으며, 이전 버전보다 훨씬 빠르게 실행됩니다. + +이 파일 관리자는 Vim과 동일한 원칙, 즉 상태 제어 키보드 동작을 기반으로 설계되었습니다. 상태의 수는 고정이 안되어 있지만, 그러나 매우 프로그래머블합니다. 그러므로, 키보드 설정들의 무한한 수는 생성 될 수 있고 사용될 수 있습니다. 이것은 다른 파일 매니저들과 다른 주요점입니다. There are themes and extensions available to download from GitHub. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx new file mode 100644 index 00000000000..57eda38f981 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx @@ -0,0 +1,10 @@ +# Molley Wallet + +```mdx-code-block +

+ +
+

+``` + +[Molly Wallet](https://github.com/grvlle/constellation_wallet/) 은 Constellation Network의 공식 $DAG 지갑입니다. 이를 통해 사용자는 $DAG 트랜잭션 생성에 국한되지 않고 다양한 방식으로 Hypergraph Network와 상호 작용할 수 있습니다. diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/october.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/october.mdx rename to website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx new file mode 100644 index 00000000000..6bc28218bc5 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx @@ -0,0 +1,10 @@ +# 옵티머스(Optimus) + +```mdx-code-block +

+ +
+

+``` + +[Optimus](https://github.com/splode/optimus) 데스크탑 이미지 최적화 애플리케이션입니다. WebP, JPEG, PNG 이미지 포맷 형식간의 변환 및 압축을 지원합니다. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx new file mode 100644 index 00000000000..f174364c13d --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx @@ -0,0 +1,10 @@ +# 포트폴(Portfall) + +```mdx-code-block +

+ +
+

+``` + +[Portfall](https://github.com/rekon-oss/portfall) - 모든 클러스터 UI에 쉽게 액세스할 수 있는 데스크탑 k8s 포트 포워딩 포털입니다. diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/restic-browser.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/restic-browser.mdx rename to website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/riftshare.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/riftshare.mdx rename to website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/scriptbar.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/scriptbar.mdx rename to website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/surge.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/surge.mdx rename to website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx new file mode 100644 index 00000000000..e3124bab727 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx @@ -0,0 +1,11 @@ +# Tiny RDM + +```mdx-code-block +

+ + +
+

+``` + +The [Tiny RDM](https://redis.tinycraft.cc/) application is an open-source, modern lightweight Redis GUI. It has a beautful UI, intuitive Redis database management, and compatible with Windows, Mac, and Linux. It provides visual key-value data operations, supports various data decoding and viewing options, built-in console for executing commands, slow log queries and more. diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/wally.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/wally.mdx rename to website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx new file mode 100644 index 00000000000..950dc3f3db1 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx @@ -0,0 +1,19 @@ +# Minecraft launcher for WarMine + +```mdx-code-block +

+ + +
+

+``` + +[Minecraft launcher for WarMine](https://warmine.ru/) is a Wails application, that allows you to easily join modded game servers and manage your game accounts. + +The Launcher downloads the game files, checks their integrity and launches the game with a wide range of customization options for the launch arguments from the backend. + +Frontend is written in Svelte, whole launcher fits in 9MB and supports Windows 7-11. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx new file mode 100644 index 00000000000..b2dc9302a9c --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx @@ -0,0 +1,10 @@ +# 웜뱃(Wombat) + +```mdx-code-block +

+ +
+

+``` + +[Wombat](https://github.com/rogchap/wombat) 은 크로스 플랫폼인 gRPC 클라이언트 입니다. diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/ytd.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/ytd.mdx rename to website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx new file mode 100644 index 00000000000..6ecbac37ee8 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx @@ -0,0 +1,69 @@ +--- +sidebar_position: 1 +--- + +# Templates + +This page serves as a list for community supported templates. Please submit a PR (click `Edit this page` at the bottom) to include your templates. To build your own template, please see the [Templates](../guides/templates.mdx) guide. + +To use these templates, run `wails init -n "Your Project Name" -t [the link below[@version]]` + +If there is no version suffix, the main branch code template is used by default. If there is a version suffix, the code template corresponding to the tag of this version is used. + +Example: `wails init -n "Your Project Name" -t https://github.com/misitebao/wails-template-vue` + +:::warning Attention + +**The Wails project does not maintain, is not responsible nor liable for 3rd party templates!** + +If you are unsure about a template, inspect `package.json` and `wails.json` for what scripts are run and what packages are installed. + +::: + +## Vue + +- [wails-template-vue](https://github.com/misitebao/wails-template-vue) - Wails template based on Vue ecology (Integrated TypeScript, Dark theme, Internationalization, Single page routing, TailwindCSS) +- [wails-vite-vue-ts](https://github.com/codydbentley/wails-vite-vue-ts) - Vue 3 TypeScript with Vite (and instructions to add features) +- [wails-vite-vue-the-works](https://github.com/codydbentley/wails-vite-vue-the-works) - Vue 3 TypeScript with Vite, Vuex, Vue Router, Sass, and ESLint + Prettier +- [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - A template using JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier) +- [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - A template using TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier, Composition API with <script setup>) +- [wails-template-naive](https://github.com/tk103331/wails-template-naive) - Wails template based on Naive UI (A Vue 3 Component Library) + +## Angular + +- [wails-template-angular](https://github.com/mateothegreat/wails-template-angular) - Angular 15+ action packed & ready to roll to production. +- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - Angular with TypeScript, Sass, Hot-Reload, Code-Splitting and i18n + +## React + +- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - A template using reactjs +- [wails-react-template](https://github.com/flin7/wails-react-template) - A minimal template for React that supports live development +- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - A template using Next.js and TypeScript +- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - A template for React + TypeScript + Vite + TailwindCSS +- [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - A template with Vite, React, TypeScript, TailwindCSS, and shadcn/ui + +## Svelte + +- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - A template using Svelte +- [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - A template using Svelte and Vite +- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - A template using Svelte and Vite with TailwindCSS v3 +- [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - An updated template using Svelte v4.2.0 and Vite with TailwindCSS v3.3.3 +- [wails-sveltekit-template](https://github.com/h8gi/wails-sveltekit-template) - A template using SvelteKit + +## Solid + +- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-ts) - A template using Solid + Ts + Vite +- [wails-template-vite-solid-js](https://github.com/xijaja/wails-template-solid-js) - A template using Solid + Js + Vite + +## Elm + +- [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - Develop your GUI app with functional programming and a **snappy** hot-reload setup :tada: :rocket: +- [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - Combine the powers :muscle: of Elm + Tailwind CSS + Wails! Hot reloading supported. + +## HTMX + +- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - Use a unique combination of pure htmx for interactivity plus templ for creating components and forms + +## Pure JavaScript (Vanilla) + +- [wails-pure-js-template](https://github.com/KiddoV/wails-pure-js-template) - A template with nothing but just basic JavaScript, HTML, and CSS diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx new file mode 100644 index 00000000000..57d509dfef7 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx @@ -0,0 +1,22 @@ +--- +sidebar_position: 6 +--- + +# 프로젝트 컴파일 + +프로젝트 디렉토리에서 `wails build` 명령을 실행합니다. 이것은 프로젝트를 컴파일하고 `build/bin` 디렉토리에 프로덕션-준비(production-ready) 바이너리를 저장합니다. + +바이너리를 실행하면 기본 애플리케이션이 표시되어야 합니다: + +```mdx-code-block +
+ +
+
+``` + +컴파일 옵션에 대한 자세한 내용은 [CLI Reference](../reference/cli.mdx#build)를 참조하세요. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx new file mode 100644 index 00000000000..5d0d9185cf4 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx @@ -0,0 +1,16 @@ +--- +sidebar_position: 5 +--- + +# 애플리케이션 개발하기 + +프로젝트 디렉토리에서 `wails dev` 명령을 실행하여 개발 모드에서 애플리케이션을 실행할 수 있습니다. 이렇게 하면 다음 작업이 수행됩니다. + +- 애플리케이션 빌드 및 실행 +- JavaScript에서 호출할 수 있도록 Go 코드를 프론트엔드에 바인딩 +- [Vite](https://vitejs.dev/)의 기능을 사용하여 Go 파일의 수정 사항을 감시하고 변경 시 다시 빌드/재실행 합니다. +- 브라우저를 통해 애플리케이션을 제공할 [Webserver](http://localhost:34115) 를 설정합니다. 이렇게 하면 브라우저 확장을 사용할 수 있습니다. 콘솔에서 Go 코드를 호출할 수도 있습니다. + +시작하려면, 프로젝트 디렉토리 내에서 `wails dev` 명령을 실행하세요. 더많은 정보는 [here](../reference/cli.mdx#dev) 에서 찾을 수 있습니다. + +출시 예정: 튜토리얼 diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx new file mode 100644 index 00000000000..45f2aa8a57e --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 2 +--- + +# 프로젝트 생성하기 + +## 프로젝트 생성 + +이제 CLI가 설치되었습니다, `wails init` 명령을 사용하여 새로운 프로젝트를 생성할 수 있습니다. + +원하는 프레임워크를 선택하세요: + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + Generate a Svelte project using JavaScript with:

+ + wails init -n myproject -t svelte + +If you would rather use TypeScript:
+ + wails init -n myproject -t svelte-ts + +
+ + Generate a React project using JavaScript with:

+ + wails init -n myproject -t react + +If you would rather use TypeScript:
+ + wails init -n myproject -t react-ts + +
+ + Generate a Vue project using JavaScript with:

+ + wails init -n myproject -t vue + +If you would rather use TypeScript:
+ + wails init -n myproject -t vue-ts + +
+ + Generate a Preact project using JavaScript with:

+ + wails init -n myproject -t preact + +If you would rather use TypeScript:
+ + wails init -n myproject -t preact-ts + +
+ + Generate a Lit project using JavaScript with:

+ + wails init -n myproject -t lit + +If you would rather use TypeScript:
+ + wails init -n myproject -t lit-ts + +
+ + Generate a Vanilla project using JavaScript with:

+ + wails init -n myproject -t vanilla + +If you would rather use TypeScript:
+ + wails init -n myproject -t vanilla-ts + +
+
+``` + +
+ +다양한 기능과 프레임워크를 제공하는 [커뮤니티 템플릿](../community/templates.mdx)도 있습니다. + +사용 가능한 다른 옵션을 보려면 `wails init -help` 명령을 실행할 수 있습니다. 자세한 내용은 [CLI Reference](../reference/cli.mdx#init)에서 찾을 수 있습니다. + +## 프로젝트 레이아웃 + +Wails 프로젝트는 다음 레이아웃을 따릅니다: + +``` +. +├── build/ +│ ├── appicon.png +│ ├── darwin/ +│ └── windows/ +├── frontend/ +├── go.mod +├── go.sum +├── main.go +└── wails.json +``` + +### 프로젝트 구조 개요 + +- `/main.go` - 메인 애플리케이션 +- `/frontend/` - Frontend 프로젝트 파일들 +- `/build/` - 프로젝트 빌드 디렉토리 +- `/build/appicon.png` - 애플리케이션 아이콘 +- `/build/darwin/` - Mac 특정 프로젝트 파일 +- `/build/windows/` - Windows 특정 프로젝트 파일 +- `/wails.json` - 프로젝트 구성 파일 +- `/go.mod` - Go 모듈 파일 +- `/go.sum` - Go 모듈 체크섬 파일 + +`frontend` 프론트엔드 디렉토리에는 Wails와 관련된 것이 없으며 선택한 모든 프론트엔드 프로젝트가 될 수 있습니다. + +`build` 디렉토리는 빌드가 진행되는 동안 사용됩니다. 이 파일들을 업데이트 하여 빌드를 커스텀마이징할 수 있습니다. 만약 빌드 디렉토리에서 파일이 제거되면 기본 버전이 재생성됩니다. + +`go.mod`의 기본 모듈 이름은 "changeme" 입니다. 이것을 더 적절한 것으로 변경해야 합니다. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx new file mode 100644 index 00000000000..1d911d11802 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx @@ -0,0 +1,89 @@ +--- +sidebar_position: 1 +--- + +# 설치하기 + +## 지원되는 플랫폼 + +- Windows 10/11 AMD64/ARM64 +- MacOS 10.13+ AMD64 +- MacOS 11.0+ ARM64 +- Linux AMD64/ARM64 + +## 의존성 + +Wails는 설치 전에 아래와 같은 몇 가지 공통적인 의존성이 필요합니다. + +- Go 1.18+ +- NPM (Node 15+) + +### Go + +[Go 다운로드 페이지](https://go.dev/dl/)에서 Go를 다운로드 합니다. + +공식 [Go 설치 지침](https://go.dev/doc/install)에 따라 진행하세요. 또한 `PATH` 환경 변수에 `~/go/bin` 디렉토리에 대한 경로도 포함되어 있는지 확인해야 합니다. 터미널을 다시 시작하고 아래 내용을 확인하세요. + +- Go가 정상적으로 설치되었는지 확인: `go version` +- PATH 변수에 "~/go/bin" 확인: `echo $PATH | grep go/bin` + +### NPM + +[Node 다운로드 페이지](https://nodejs.org/en/download/)에서 NPM을 다운로드 합니다. 우리는 일반적으로 최신 버전에서 테스트를 진행하기 때문에 최신 버전 사용을 권장합니다. + +정상적으로 설치된 것을 확인하기 위해 `npm --version`을 실행합니다. + +## 플랫폼에 따른 의존성 + +플랫폼별 의존 항목도 설치해야 합니다: + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + Wails 는 xcode line tools 설치를 필요로 합니다. xcode-select --install. 를 실행하여 수행할 수 있습니다. + + + Wails 는 WebView2 런타임 설치를 필요로 합니다. 몇몇 Windows는 이미 설치되어 있습니다. wails doctor 명령을 사용하여 확인할 수 있습니다. + + + Linux requires the standard gcc build tools plus libgtk3 and libwebkit. 다양한 배포판에 대한 수 많은 명령을 나열하는 대신 Wail는 특정 배포판에 대한 설치 명령이 무엇인지 결정할 수 있습니다. wails doctor 명령을 실행하면 설치 후 종속성을 설치하는 방법을 보여줍니다. 만약 배포판/패키지 매니저가 지원하지 않는다면, 를 통해 문의하세요. 리눅스 배포판 추가 가이드 + + +``` + +## 선택 설치 + +- [UPX](https://upx.github.io/) 는 애플리케이션 압축을 위함. +- [NSIS](https://wails.io/docs/guides/windows-installer/) 는 윈도우 인스톨러를 생성하기 위함. + +## Wails 설치 + +`go install github.com/wailsapp/wails/v2/cmd/wails@latest` 명령을 실행하여 Wails CLI를 설치합니다. + +참고: 다음과 비슷한 오류가 발생하는 경우: + +```shell +....\Go\pkg\mod\github.com\wailsapp\wails\v2@v2.1.0\pkg\templates\templates.go:28:12: pattern all:ides/*: no matching files found +``` +Go 1.18 이상의 버전이 설치되어 있는지 확인하세요: +```shell +go version +``` + +## 시스템 점검 + +`wails doctor`를 실행하면 의존성이 올바르게 설치되어 있는지 점검할 수 있습니다. 문제가 있는 의존성에 대해서는 문제 해결을 위한 도움을 줄 수 있습니다. + +## `wails` 명령이 사라졌다고 나오나요? + +시스템에서 `wails` 명령이 누락되었다고 뜨는 경우 Go 설치 가이드를 바르게 따랐는지 확인하세요. 일반적으로, 사용자의 홈 디렉토리에 있는 `go/bin` 디렉토리가 `PATH` 환경 변수에 없음을 의미합니다. 또한, 설치 프로그램이 수행한 환경 변경 사항이 명령 프롬프트에 반영되도록 일반적으로 열려 있는 모든 명령 프롬프트를 닫았다가 다시 열어야합니다. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx new file mode 100644 index 00000000000..1b21f9daa7a --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx @@ -0,0 +1,14 @@ +# Angular + +Wails에는 Angular 템플릿이 없지만 Wails와 함께 Angular를 사용할 수 있습니다. + +## 개발자 모드 + +Angular에서 작동하는 개발 모드를 사용하려면 `wails.json`에 다음을 추가해야 합니다. + +```json + "frontend:build": "npx ng build", + "frontend:install": "npm install", + "frontend:dev:watcher": "npx ng serve", + "frontend:dev:serverUrl": "http://localhost:4200", +``` \ No newline at end of file diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx new file mode 100644 index 00000000000..e4251eba409 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx @@ -0,0 +1,215 @@ +# 애플리케이션 개발 + +Wails로 애플리케이션을 개발하기 위한 엄격한 규칙은 없으나 몇 가지의 기본 가이드가 있습니다. + +## 애플리케이션 셋업 + +기본 템플릿에서 사용되는 패턴은 `main.go`가 애플리케이션 구성 및 실행에 사용되는 반면 `app.go`는 애플리케이션 로직 정의에 사용된다는 것입니다. + +`app.go` 파일은 기본 애플리케이션에 hook 역할을 하는 2개의 메소드가 있는 구조체를 정의합니다. + +```go title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} +``` + +- 시작 메서드는 Wails가 필요한 리소스를 할당하는 즉시 호출되며 리소스 생성, 이벤트 리스너 설정 및 시작 시 응용 프로그램에 필요한 모든 것을 설정하기에 좋은 위치입니다. 일반적으로 구조체 필드에 저장되는 `context.Context`가 제공됩니다. 이 컨텍스트는 [런타임](../reference/runtime/intro.mdx)을 호출하는 데 필요합니다. 이 메서드가 오류를 반환하면 응용 프로그램이 종료됩니다. 개발 모드에서는 오류가 콘솔에 출력됩니다. + +- Shutdown 메소드는 shutdown 프로세스가 끝날 때 바로 Wails에 의해 호출됩니다. 이것은 메모리 할당을 해제하고 모든 shutodown 작업을 수행하기에 좋은 위치입니다. + +`main.go` 파일은 일반적으로 애플리케이션 구성을 허용하는 `wails.Run()`에 대한 단일 호출로 구성됩니다. 템플릿에서 사용하는 패턴은 `wails.Run()`을 호출하기 전에 `app.go`에서 정의한 구조체의 인스턴스가 생성되어 변수에 저장된다는 것입니다. 이것은 `app`이라고 합니다. 이 configuration 은 콜백을 추가하는 위치입니다: + +```go {3,9,10} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +애플리케이션 lifecycle hook에 대한 자세한 내용은 [여기](../howdoesitwork.mdx#application-lifecycle-callbacks)에서 확인할 수 있습니다. + +## 바인딩 메소드 + +프론트엔드에서 Go 메서드를 호출할 가능성이 높습니다. 이는 일반적으로 `app.go`에서 이미 정의된 구조체에 public method를 추가하여 수행됩니다. + +```go {16-18} title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +메인 어플리케이션 구성에서, `Bind` 키는 Wails에 무엇을 바인딩할지 알릴 수 있는 부분입니다. + +```go {11-13} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +이렇게 하면 `App` 구조체의 모든 공개 메서드가 바인딩됩니다(시작 및 종료 메서드는 바인딩되지 않음). + +### 여러 구조체를 바인딩할 때의 컨텍스트 처리 + +여러 구조체에 대한 메서드를 바인딩하고 싶지만 런타임을 사용할 수 있도록 각 구조체가 컨텍스트에 대한 참조를 유지하기를 원하는 경우, 함수에서 좋은 패턴은 `OnStartup` 메서드에서 구조체 인스턴스로 컨텍스트를 전달하는 것입니다. + +```go +func main() { + + app := NewApp() + otherStruct := NewOtherStruct() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: func(ctx context.Context){ + app.SetContext(ctx) + otherStruct.SetContext(ctx) + }, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + otherStruct + }, + }) + if err != nil { + log.Fatal(err) + } +} +``` + +바인딩에 대한 더 많은 정보는 [여기](../howdoesitwork.mdx#method-binding)에서 확인할 수 있습니다. + +## Application Menu + +Wails는 당신의 애플리케이션에 메뉴 추가를 지원합니다. 이것은 [Menu](../reference/menus.mdx#menu) 구조체를 애플리케이션 구성에 전달하여 수행됩니다. Menu를 반환하는 메서드를 사용하는 것이 일반적이며 lifecycle hooks에 사용되는 `App` 구조체의 메서드인 경우에는 훨씬 더 일반적입니다. + +```go {11} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Menu: app.menu(), + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +## Assets + +Wails v2가 assets을 처리하는 방식의 장점은 그렇지 않다는 것입니다! Wails에 제공해야 하는 유일한 것은 `embed.FS`입니다. 당신이 어떻게 얻어내는가는 전적으로 당신에게 달렸습니다. 바닐라 템플릿과 같은 바닐라 html/css/js를 사용할 수 있습니다. 복잡한 빌드 시스템을 가질 수 있으나, 중요하지 않습니다. + +`wails build`가 실행되면 프로젝트 최상위에서 `wails.json` 프로젝트 파일을 확인합니다. 프로젝트 파일에는 2개의 키가 있습니다. + +- "frontend:install" +- "frontend:build" + +첫 번째는 노드 모듈을 설치하기 위해 `frontend` 디렉토리에서 실행됩니다. 두 번째는 프런트엔드 프로젝트를 빌드하기 위해 `frontend` 디렉토리에서 실행됩니다. + +이 2개의 키가 주어지지 않으면 Wails는 프런트엔드에서 아무 작업도 수행하지 않습니다. 그것은 `embed.FS`에서만 기대합니다. + +### AssetsHandler + +Wails v2 앱은 선택적으로 `options.App`에서 `http.Handler`를 정의할 수 있습니다. 즉석에서 파일을 생성하거나 POST/PUT 요청을 처리합니다. GET 요청은 항상 `assets` FS에서 먼저 처리됩니다. FS가 요청된 파일을 찾지 못하면 요청은 제공을 위해 `http.Handler`로 전달됩니다. GET 이외의 모든 요청은 지정된 경우 `AssetsHandler`에서 직접 처리됩니다. `Assets` 옵션으로 `nil`을 지정하여 `AssetsHandler`만 사용할 수도 있습니다. + +## Built in Dev Server + +`wails dev`를 실행하면 내장된 dev 서버가 시작되어 프로젝트 디렉토리에서 file watcher를 시작합니다. 기본적으로 파일이 변경되면 wails는 응용 프로그램 파일인지 확인합니다(기본값: `.go`, `-e` 플래그로 구성 가능). 그렇다면 응용 프로그램을 다시 빌드하고 다시 시작합니다. 변경된 파일이 assets에 있는 경우 짧은 시간 후에 다시 로드를 발행합니다. + +개발 서버는 "debouncing"이라는 기술을 사용합니다. 즉, 짧은 시간에 여러 파일이 변경될 수 있으므로 바로 다시 로드되지 않습니다. 트리거가 발생하면 다시 로드하기 전에 설정된 시간 동안 기다립니다. 다른 트리거가 발생하면 다시 대기 시간으로 재설정됩니다. 기본 값은 `100ms` 입니다. 이 값이 프로젝트에서 작동하지 않는 경우 `-debounce` 플래그를 사용하여 구성할 수 있습니다. 사용하는 경우 이 값은 프로젝트 구성에 저장되고 기본값이 됩니다. + +## External Dev Server + +일부 프레임워크는 자체 라이브 리로딩 서버와 함께 제공되지만 Wails Go 바인딩을 활용할 수 없습니다. 이 시나리오에서는 Wails가 감시할 빌드 디렉토리에 프로젝트를 다시 빌드하는 watcher script를 실행하는 것이 가장 좋습니다. 예를 보려면 [rollup](https://rollupjs.org/guide/en/)을 사용하는 기본 svelte 템플릿을 참조하세요. + +### Create React App + +The process for a Create-React-App project is slightly more complicated. In order to support live frontend reloading the following configuration needs to be added to your `wails.json`: + +```json + "frontend:dev:watcher": "yarn start", + "frontend:dev:serverUrl": "http://localhost:3000", +``` + +The `frontend:dev:watcher` command will start the Create-React-App development server (hosted on port `3000` typically). The `frontend:dev:serverUrl` command then instructs Wails to serve assets from the development server when loading the frontend rather than from the build folder. In addition to the above, the `index.html` needs to be updated with the following: + +```html + + + + + +``` + +This is required as the watcher command that rebuilds the frontend prevents Wails from injecting the required scripts. This circumvents that issue by ensuring the scripts are always injected. With this configuration, `wails dev` can be run which will appropriately build the frontend and backend with hot-reloading enabled. Additionally, when accessing the application from a browser the React developer tools can now be used on a non-minified version of the application for straightforward debugging. Finally, for faster builds, `wails dev -s` can be run to skip the default building of the frontend by Wails as this is an unnecessary step. + +## Go Module + +기본 Wails 템플릿은 "changeme"라는 모듈 이름이 포함된 `go.mod` 파일을 생성합니다. 프로젝트 생성 후에 이 파일의 이름을 변경해야 합니다. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx new file mode 100644 index 00000000000..fd81a974d04 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx @@ -0,0 +1,66 @@ +# Crossplatform build with Github Actions + +To build a Wails project for all the available platforms, you need to create an application build for each operating system. One effective method to achieve this is by utilizing GitHub Actions. + +An action that facilitates building a Wails app is available at: +https://github.com/dAppServer/wails-build-action + +In case the existing action doesn't fulfill your requirements, you can select only the necessary steps from the source: +https://github.com/dAppServer/wails-build-action/blob/main/action.yml + +Below is a comprehensive example that demonstrates building an app upon the creation of a new Git tag and subsequently uploading it to the Actions artifacts: + +```yaml +name: Wails build + +on: + push: + tags: + # Match any new tag + - '*' + +env: + # Necessary for most environments as build failure can occur due to OOM issues + NODE_OPTIONS: "--max-old-space-size=4096" + +jobs: + build: + strategy: + # Failure in one platform build won't impact the others + fail-fast: false + matrix: + build: + - name: 'App' + platform: 'linux/amd64' + os: 'ubuntu-latest' + - name: 'App' + platform: 'windows/amd64' + os: 'windows-latest' + - name: 'App' + platform: 'darwin/universal' + os: 'macos-latest' + + runs-on: ${{ matrix.build.os }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Build wails + uses: dAppServer/wails-build-action@v2.2 + id: build + with: + build-name: ${{ matrix.build.name }} + build-platform: ${{ matrix.build.platform }} + package: false + go-version: '1.20' +``` + +This example offers opportunities for various enhancements, including: + +- Caching dependencies +- Code signing +- Uploading to platforms like S3, Supbase, etc. +- Injecting secrets as environment variables +- Utilizing environment variables as build variables (such as version variable extracted from the current Git tag) diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx new file mode 100644 index 00000000000..e86b651845d --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx @@ -0,0 +1,204 @@ +# Custom Protocol Scheme association + +Custom Protocols feature allows you to associate specific custom protocol with your app so that when users open links with this protocol, +your app is launched to handle them. This can be particularly useful to connect your desktop app with your web app. +In this guide, we'll walk through the steps to implement custom protocols in Wails app. + +## Set Up Custom Protocol Schemes Association: + +To set up custom protocol, you need to modify your application's wails.json file. +In "info" section add a "protocols" section specifying the protocols your app should be associated with. + +For example: + +```json +{ + "info": { + "protocols": [ + { + "scheme": "myapp", + "description": "My App Protocol", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------ | +| scheme | Custom Protocol scheme. e.g. myapp | +| description | Windows-only. The description. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open custom protocol with your app, the system will launch your app and call the `OnUrlOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnUrlOpen: func(url string) { println(url) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows Custom Protocol Schemes is supported only with NSIS installer. During installation, the installer will create a +registry entry for your schemes. When you open url with your app, new instance of app is launched and url is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there (note that `%u` is important in Exec). Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=x-scheme-handler/myapp; +``` + +2. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +``` + +3. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with custom protocol scheme. When you open url with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx new file mode 100644 index 00000000000..989202e27a6 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx @@ -0,0 +1,136 @@ +# Dynamic Assets + +If you want to load or generate assets for your frontend dynamically, you can achieve that using the [AssetsHandler](../reference/options#assetshandler) option. The AssetsHandler is a generic `http.Handler` which will be called for any non GET request on the assets server and for GET requests which can not be served from the bundled assets because the file is not found. + +By installing a custom AssetsHandler, you can serve your own assets using a custom asset server. + +## Example + +In our example project, we will create a simple assets handler which will load files off disk: + +```go title=main.go {17-36,49} +package main + +import ( + "embed" + "fmt" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "net/http" + "os" + "strings" +) + +//go:embed all:frontend/dist +var assets embed.FS + +type FileLoader struct { + http.Handler +} + +func NewFileLoader() *FileLoader { + return &FileLoader{} +} + +func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) { + var err error + requestedFilename := strings.TrimPrefix(req.URL.Path, "/") + println("Requesting file:", requestedFilename) + fileData, err := os.ReadFile(requestedFilename) + if err != nil { + res.WriteHeader(http.StatusBadRequest) + res.Write([]byte(fmt.Sprintf("Could not load file %s", requestedFilename))) + } + + res.Write(fileData) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "helloworld", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: NewFileLoader(), + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 255}, + OnStartup: app.startup, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +When we run the application in dev mode using `wails dev`, we will see the following output: + +``` +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' failed, using AssetHandler +Requesting file: favicon.ico +``` + +As you can see, the assets handler is called when the default assets server is unable to serve the `favicon.ico` file. + +If you right click the main application and select "inspect" to bring up the devtools, you can test this feature out by typing the following into the console: + +``` +let response = await fetch('does-not-exist.txt'); +``` + +This will generate an error in the devtools. We can see that the error is what we expect, returned by our custom assets handler: + +```mdx-code-block +

+ +

+``` + +However, if we request `go.mod`, we will see the following output: + +```mdx-code-block +

+ +

+``` + +This technique can be used to load images directly into the page. If we updated our default vanilla template and replaced the logo image: + +```html + +``` + +with: + +```html + +``` + +Then we would see the following: + +```mdx-code-block +

+ +

+``` + +:::warning + +Exposing your filesystem in this way is a security risk. It is recommended that you properly manage access to your filesystem. + +::: diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx new file mode 100644 index 00000000000..167955b12d7 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx @@ -0,0 +1,244 @@ +# File Association + +File association feature allows you to associate specific file types with your app so that when users open those files, +your app is launched to handle them. This can be particularly useful for text editors, image viewers, or any application +that works with specific file formats. In this guide, we'll walk through the steps to implement file association in Wails app. + +## Set Up File Association: + +To set up file association, you need to modify your application's wails.json file. +In "info" section add a "fileAssociations" section specifying the file types your app should be associated with. + +For example: + +```json +{ + "info": { + "fileAssociations": [ + { + "ext": "wails", + "name": "Wails", + "description": "Wails Application File", + "iconName": "wailsFileIcon", + "role": "Editor" + }, + { + "ext": "jpg", + "name": "JPEG", + "description": "Image File", + "iconName": "jpegFileIcon", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | +| ext | The extension (minus the leading period). e.g. png | +| name | The name. e.g. PNG File | +| iconName | The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows | +| description | Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open file (or files) with your app, the system will launch your app and call the `OnFileOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnFileOpen: func(filePaths []string) { println(filestring) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows file association is supported only with NSIS installer. During installation, the installer will create a +registry entry for your file associations. When you open file with your app, new instance of app is launched and file path is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there. Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=application/x-wails;application/x-test +``` + +2. Create mime types file. Example: + +```xml + + + + Wails Application File + + + +``` + +3. Create icons for your file types. SVG icons are recommended. +4. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload mime types to register file associations +update-mime-database /usr/share/mime +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +# update icons +update-icon-caches /usr/share/icons/* +``` + +5. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ./application-wails-mime.xml + dst: /usr/share/mime/packages/application-x-wails.xml +- src: ./application-test-mime.xml + dst: /usr/share/mime/packages/application-x-test.xml +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with specified file types. When you open file with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx new file mode 100644 index 00000000000..3845736f427 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx @@ -0,0 +1,87 @@ +# Frameless Applications + +Wails supports application that have no frames. This can be achieved by using the [frameless](../reference/options.mdx#frameless) field in [Application Options](../reference/options.mdx#application-options). + +Wails offers a simple solution for dragging the window: Any HTML element that has the CSS style `--wails-draggable:drag` will act as a "drag handle". This property applies to all child elements. If you need to indicate that a nested element should not drag, then use the attribute '--wails-draggable:no-drag' on that element. + +```html + + + + + + + +
+ + +
+
+ + + + +``` + +For some projects, using a CSS variable may not be possible due to dynamic styling. In this case, you can use the `CSSDragProperty` and `CSSDragValue` application options to define a property and value that will be used to indicate draggable regions: + +```go title=main.go +package main + +import ( + "embed" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "alwaysontop", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Frameless: true, + CSSDragProperty: "widows", + CSSDragValue: "1", + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +```html title=index.html + + + + + + alwaysontop + + +
+ + + +``` + +:::info Fullscreen + +If you allow your application to go fullscreen, this drag functionality will be disabled. + +::: diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx new file mode 100644 index 00000000000..ac087ee4514 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx @@ -0,0 +1,72 @@ +# Frontend + +## Script Injection + +When Wails serves your `index.html`, by default, it will inject 2 script entries into the `` tag to load `/wails/ipc.js` and `/wails/runtime.js`. These files install the bindings and runtime respectively. + +The code below shows where these are injected by default: + +```html + + + injection example + + + + + + + +
Please enter your name below 👇
+
+ + +
+ + + + +``` + +### Overriding Default Script Injection + +To provide more flexibility to developers, there is a meta tag that may be used to customise this behaviour: + +```html + +``` + +The options are as follows: + +| Value | Description | +| ------------------- | ------------------------------------------------ | +| noautoinjectruntime | Disable the autoinjection of `/wails/runtime.js` | +| noautoinjectipc | Disable the autoinjection of `/wails/ipc.js` | +| noautoinject | Disable all autoinjection of scripts | + +Multiple options may be used provided they are comma seperated. + +This code is perfectly valid and operates the same as the autoinjection version: + +```html + + + injection example + + + + + + +
Please enter your name below 👇
+
+ + +
+ + + + + + +``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx new file mode 100644 index 00000000000..f742822832a --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx @@ -0,0 +1,127 @@ +# IDEs + +Wails aims to provide a great development experience. To that aim, we now support generating IDE specific configuration to provide smoother project setup. + +Currently, we support [Visual Studio Code](https://code.visualstudio.com/) but aim to support other IDEs such as Goland. + +## Visual Studio Code + +```mdx-code-block +

+ +

+``` + +When generating a project using the `-ide vscode` flags, IDE files will be created alongside the other project files. These files are placed into the `.vscode` directory and provide the correct configuration for debugging your application. + +The 2 files generated are `tasks.json` and `launch.json`. Below are the files generated for the default vanilla project: + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/myproject.exe" + ] + } + ] +} +``` + +```json title="launch.json" +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Wails: Debug myproject", + "type": "go", + "request": "launch", + "mode": "exec", + "program": "${workspaceFolder}/build/bin/myproject.exe", + "preLaunchTask": "build", + "cwd": "${workspaceFolder}", + "env": {} + } + ] +} +``` + +### Configuring the install and build steps + +The `tasks.json` file is simple for the default project as there is no `npm install` or `npm run build` step needed. For projects that have a frontend build step, such as the svelte template, we would need to edit `tasks.json` to add the install and build steps: + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "npm install", + "type": "npm", + "script": "install", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "npm run build", + "type": "npm", + "script": "build", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/vscode.exe" + ], + "dependsOn": ["npm install", "npm run build"] + } + ] +} +``` + +:::info Future Enhancement + +In the future, we hope to generate a `tasks.json` that includes the install and build steps automatically. + +::: diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx new file mode 100644 index 00000000000..8b25c15754a --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx @@ -0,0 +1,103 @@ +# Linux Distro Support + +## Overview + +Wails offers Linux support but providing installation instructions for all available distributions is an impossible task. Instead, Wails tries to determine if the packages you need to develop applications are available via your system's package manager. Currently, we support the following package managers: + +- apt +- dnf +- emerge +- eopkg +- nixpkgs +- pacman +- zypper + +## Adding package names + +There may be circumstances where your distro uses one of the supported package managers but the package name is different. For example, you may use an Ubuntu derivative, but the package name for gtk may be different. Wails attempts to find the correct package by iterating through a list of package names. The list of packages are stored in the packagemanager specific file in the `v2/internal/system/packagemanager` directory. In our example, this would be `v2/internal/system/packagemanager/apt.go`. + +In this file, the list of packages are defined by the `Packages()` method: + +```go +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +Let's assume that in our linux distro, `libgtk-3` is packaged under the name `lib-gtk3-dev`. We could add support for this by adding the following line: + +```go {5} +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + {Name: "lib-gtk3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +## Adding new package managers + +To add a new package manager, perform the following steps: + +- Create a new file in `v2/internal/system/packagemanager` called `.go`, where `` is the name of the package manager. +- Define a struct that conforms to the package manager interface defined in `pm.go`: + +```go +type PackageManager interface { + Name() string + Packages() packagemap + PackageInstalled(*Package) (bool, error) + PackageAvailable(*Package) (bool, error) + InstallCommand(*Package) string +} +``` + +- `Name()` should return the name of the package manager +- `Packages()` should return a `packagemap`, that provides candidate filenames for dependencies +- `PackageInstalled()` should return `true` if the given package is installed +- `PackageAvailable()` should return `true` if the given package is not installed but available for installation +- `InstallCommand()` should return the exact command to install the given package name + +Take a look at the other package managers code to get an idea how this works. + +:::info Remember + +If you add support for a new package manager, don't forget to also update this page! + +::: diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx new file mode 100644 index 00000000000..229c282bf55 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx @@ -0,0 +1,18 @@ +# Linux + +This page has miscellaneous guides related to developing Wails applications for Linux. + +## Video tag doesn't fire "ended" event + +When using a video tag, the "ended" event is not fired when the video is finished playing. This is a bug in WebkitGTK, however you can use the following workaround to fix it: + +```js +videoTag.addEventListener("timeupdate", (event) => { + if (event.target.duration - event.target.currentTime < 0.2) { + let ended = new Event("ended"); + event.target.dispatchEvent(ended); + } +}); +``` + +Source: [Lyimmi](https://github.com/Lyimmi) on the [discussions board](https://github.com/wailsapp/wails/issues/1729#issuecomment-1212291275) diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx new file mode 100644 index 00000000000..4ba1f34c37d --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx @@ -0,0 +1,55 @@ +# Local Development + +## Overview + +Wails is in constant development and new releases are regularly "tagged". This usually happens when all the newer code on `master` has been tested and confirmed working. If you need a bugfix or feature that has not yet made it to a release, it's possible to use the latest "bleeding edge" version using the following steps: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails/v2/cmd/wails` +- `go install` + +NOTE: The directory that you cloned the project into will now be called "clonedir". + +The Wails CLI will now be at the very latest version. + +### Updating your project + +To update projects to use the latest version of the Wails library, update the project's `go.mod` and ensure the following line is at the bottom of the file: + +`replace github.com/wailsapp/wails/v2 => ` + +Example: + +On Windows: `replace github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2` + +On 'nix: `replace github.com/wailsapp/wails/v2 => /home/me/projects/wails/v2` + +To revert to a stable version, run: + +`go install github.com/wailsapp/wails/v2/cmd/wails@latest` + +## Testing a Branch + +If you want to test a branch, follow the instructions above, but ensure you switch the branch you want to test before installing: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails` +- `git checkout -b branch-to-test --track origin/branch-to-test` +- `cd v2/cmd/wails` +- `go install` + +Make sure you [update your project](#updating-your-project) as described above. + +## Testing a PR + +If you want to test a PR, follow the instructions above, but ensure you fetch the PR and switch the branch before installing. Please replace `[IDofThePR]` with the ID of the PR shown on github.com: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails` +- `git fetch -u origin pull/[IDofThePR]/head:test/pr-[IDofThePR]` +- `git checkout test/pr-[IDofThePR]` +- `git reset --hard HEAD` +- `cd v2/cmd/wails` +- `go install` + +Make sure you [update your project](#updating-your-project) as described above. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx new file mode 100644 index 00000000000..961595711c7 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx @@ -0,0 +1,97 @@ +# Mac App Store Guide + +This page gives a brief overview of how to submit your Wails App to the Mac App Store. + +## Prerequisites + +- You will need to have an Apple Developer account. Please find more information on the [Apple Developer Program](https://developer.apple.com/support/compare-memberships/) site +- You will need to have your Certificates, Identifiers, and App created on the developer portal. More on this below +- Xcode command line tools will need to be installed on your local machine + +#### Create Certificates and Identifiers + +1. Go to your [Apple Developer Account](https://developer.apple.com/account/) +2. Under `Certificates, Identifiers & Profiles`, click `Identifiers` and Register a New App ID. Use the format (com.example.app) +3. Under the same page click `Certificates` and generate new Certificates for Mac App Store Distribution. Download them and import the certificates into Keychain on your local machine. + +#### Create App Submission + +1. Go to the [App Store Connect Site](https://appstoreconnect.apple.com/apps) +2. Register a new application and link the bundle ID that you created in the previous step +3. Populate your app with the correct screen shots, descriptions, etc. as required by Apple +4. Create a new version of your app + +#### Create Provisioning Profile +1. Go to the [Apple Developer Profiles](https://developer.apple.com/account/resources/profiles/list) page +2. Add a new provisioning profile for Mac App Store Distribution +3. Set the Profile Type as Mac and select the App ID for the application created above +4. Select the Mac App Distribution certificate +5. Name the Provisioning Profile embedded and download the created profile. + +## Mac App Store Process + +#### Enable Apple's App Sandbox + +Apps submitted to the Mac App Store must run under Apple's [App Sandbox](https://developer.apple.com/app-sandboxing/). You must create an `entitlements.plist` file for this to work. The recommendation is to create this file under this path `{PROJECT_DIR}/build/darwin/entitlements.plist`. + +**Example Entitlements File** + +This is an example entitlements file from the [RiftShare](https://github.com/achhabra2/riftshare) app. For reference please put in the entitlements your app requires. Refer to [this site](https://developer.apple.com/documentation/bundleresources/entitlements) for more information. You will need to replace the Team ID and Application Name with the ones you registered above. + +```xml title="entitlements.plist" + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + com.apple.application-identifier + TEAM_ID.APP_NAME + com.apple.developer.team-identifier + TEAM_ID + + +``` + +**Add the Embedded Provisioning Profile** The Provisioning Profile created above needs to be added to the root of the applicaton. It needs to be named embedded.provisionprofile. + +#### Build and Sign the App Package + +The following is an example script for building and signing your app for Mac App Store submission. It assumes you are running the script from your root project directory. + +Note the certificates for signing the app and signing the installer are different. Please make sure both are imported into Keychain. Find the strings in Keychain and insert them below. Populate your certificate names, and app name below. Running the following script will generate a signed `app.pkg` file in the root directory of your app. + +```bash title="macappstore-build.sh" +#!/bin/bash + +APP_CERTIFICATE="3rd Party Mac Developer Application: YOUR NAME (CODE)" +PKG_CERTIFICATE="3rd Party Mac Developer Installer: YOUR NAME (CODE)" +APP_NAME="YourApp" + +wails build -platform darwin/universal -clean + +cp ./embedded.provisionprofile "./build/bin/$APP_NAME.app/Contents" + +codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist ./build/bin/$APP_NAME.app + +productbuild --sign "$PKG_CERTIFICATE" --component ./build/bin/$APP_NAME.app /Applications ./$APP_NAME.pkg +``` + +#### Upload App Bundle + +You will need to upload the generated package file and associate it to your Application before you will be able to submit it for review. + +1. Download the [Transporter App](https://apps.apple.com/us/app/transporter/id1450874784) from the Mac App Store +2. Open it and sign in with your Apple ID +3. Click the + sign and select the `APP_NAME.pkg` file that you generated in the previous step. Upload it +4. Go back to the [App Store Connect](https://appstoreconnect.apple.com/apps) site and navigate back into your app submission. Select the version that you are ready to make available on the App Store. Under `Build` select the package that you uploaded via Transporter. + +That's it! You can now use the site to submit your App for review. After a few business days if all goes well you should see your App live on the Mac App Store. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx new file mode 100644 index 00000000000..dcf192d337f --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx @@ -0,0 +1,95 @@ +# Manual Builds + +The Wails CLI does a lot of heavy lifting for the project, but sometimes it's desirable to manually build your project. This document will discuss the different operations the CLI does and how this may be achieved in different ways. + +## Build Process + +When either `wails build` or `wails dev` are used, the Wails CLI performs a common build process: + + - Install frontend dependencies + - Build frontend project + - Generate build assets + - Compile application + - [optional] Compress application + +### Install frontend dependencies + +#### CLI Steps + +- If the `-s` flag is given, this step is skipped +- Checks `wails.json` to see if there is an install command in the key `frontend:install` +- If there isn't, it skips this step +- If there is, it checks if `package.json` exists in the frontend directory. If it doesn't exist, it skips this step +- An MD5 sum is generated from the `package.json` file contents +- It checks for the existence of `package.json.md5` and if it exists, will compare the contents of it (an MD5 sum) with the one generated to see if the contents have changed. If they are the same, this step is skipped +- If `package.json.md5` does not exist, it creates it using the generated MD5 sum +- If a build is now required, or `node_modules` does not exist, or the `-f` flag is given, the install command is executed in the frontend directory + +#### Manual Steps + +This step could be done from the command line or a script with `npm install`. + +### Build frontend project + +#### Wails CLI + +- If the `-s` flag is given, this step is skipped +- Checks `wails.json` to see if there is a build command in the key `frontend:build` +- If there isn't, it skips this step +- If there is, it is executed in the frontend directory + +#### Manual Steps + +This step could be done from the command line or a script with `npm run build` or whatever the frontend build script is. + +### Generate assets + +#### Wails CLI + +- If `-nopackage` flag is set, this stage is skipped +- If the `build/appicon.png` file does not exist, a default one is created +- For Windows, see [Bundling for Windows](#windows) +- If `build/windows/icon.ico` does not exist, it will create it from the `build/appicon.png` image. + +##### Windows + +- If `build/windows/icon.ico` does not exist, it will create it from `build/appicon.png` using icon sizes of 256, 128, 64, 48, 32 and 16. This is done using [winicon](https://github.com/leaanthony/winicon). +- If the `build/windows/.manifest` file does not exist, it creates it from a default version. +- Compiles the application as a production build (above) +- Uses [winres](https://github.com/tc-hib/winres) to bundle the icon and manifest into a `.syso` file ready for linking. + +#### Manual Steps + +- Create `icon.ico` using the [winicon](https://github.com/leaanthony/winicon) CLI tool (or any other tool). +- Create / Update a `.manifest` file for your application +- Use the [winres CLI](https://github.com/tc-hib/go-winres) to generate a `.syso` file. + +### Compile application + +#### Wails CLI + +- If the `-clean` flag is provided, the `build` directory is deleted and recreated +- For `wails dev`, the following default Go flags are used: `-tags dev -gcflags "all=-N -l"` +- For `wails build`, the following default Go flags are used: `-tags desktop,production -ldflags "-w -s"` + - On Windows, `-ldflags "-w -h -H windowsgui"` +- Additional tags passed to the CLI using `-tags` are added to the defaults +- Additional ldflags passed to the CLI using `-ldflags` are added to the defaults +- The `-o` flag is passed through +- The Go compiler specified by `-compiler` will be used for compilation + +#### Manual steps + +- For dev build, the minimum command would be: `go build -tags dev -gcflags "all=-N -l"` +- For production build, the minimum command would be: `go build -tags desktop,production -ldflags "-w -s -H windowsgui"` +- Ensure that you compile in the same directory as the `.syso` file + +### Compress application + +#### Wails CLI + +- If the `-upx` flag has been given, the `upx` program will be run to compress the application with the default settings +- If `-upxflags` is also passed, these flags are used instead of the default ones + +#### Manual steps + +- Run `upx [flags]` manually to compress the application. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx new file mode 100644 index 00000000000..7123cbe6b60 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx @@ -0,0 +1,191 @@ +# Migrating from v1 + +## Overview + +Wails v2 is a significant change from v1. This document aims to highlight the changes and the steps in migrating an existing project. + +### Creating the Application + +In v1, the main application is created using `wails.CreateApp`, bindings are added with `app.Bind`, then the application is run using `app.Run()`. + +Example: + +```go title="v1" + app := wails.CreateApp(&wails.AppConfig{ + Title: "MyApp", + Width: 1024, + Height: 768, + JS: js, + CSS: css, + Colour: "#131313", + }) + app.Bind(basic) + app.Run() +``` + +In v2, there is just a single method, `wails.Run()`, that accepts [application options](../reference/options.mdx#application-options). + +```go title="v2" + err := wails.Run(&options.App{ + Title: "MyApp", + Width: 800, + Height: 600, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + basic, + }, + }) +``` + +### Binding + +In v1, it was possible to bind both arbitrary functions and structs. In v2, this has been simplified to only binding structs. The struct instances that were previously passed to the `Bind()` method in v1, are now specified in the `Bind` field of the [application options](../reference/options.mdx#application-options): + +```go title="v1" + app := wails.CreateApp(/* options */) + app.Bind(basic) +``` + +```go title="v2" + err := wails.Run(&options.App{ + /* other options */ + Bind: []interface{}{ + basic, + }, + }) +``` + +In v1, bound methods were available to the frontend at `window.backend`. This has changed to `window.go`.`` + +### Application Lifecycle + +In v1, there were 2 special methods in a bound struct: `WailsInit()` and `WailsShutdown()`. These have been replaced with 3 lifecycle hooks as part of the [application options](../reference/options.mdx#application-options): + +- [OnStartup](../reference/options.mdx#onstartup) +- [OnShutdown](../reference/options.mdx#onshutdown) +- [OnDomReady](../reference/options.mdx#ondomready) + +Note: [OnDomReady](../reference/options.mdx#ondomready) replaces the `wails:ready` system event in v1. + +These methods can be standard functions, but a common practice is to have them part of a struct: + +```go title="v2" + basic := NewBasicApp() + err := wails.Run(&options.App{ + /* Other Options */ + OnStartup: basic.startup, + OnShutdown: basic.shutdown, + OnDomReady: basic.domready, + }) +... +type Basic struct { + ctx context.Context +} +func (b *Basic) startup(ctx context.Context) { + b.ctx = ctx +} +... +``` + +### Runtime + +The runtime in v2 is much richer than v1 with support for menus, window manipulation and better dialogs. The signature of the methods has changed slightly - please refer the the [Runtime Reference](../reference/runtime/intro.mdx). + +In v1, the [runtime](../reference/runtime/intro.mdx) was available via a struct passed to `WailsInit()`. In v2, the runtime has been moved out to its own package. Each method in the runtime takes the `context.Context` that is passed to the [OnStartup](../reference/options.mdx#onstartup) method. + +```go title="Runtime Example" +package main + +import "github.com/wailsapp/wails/v2/pkg/runtime" + +type Basic struct { + ctx context.Context +} + +// startup is called at application startup +func (a *App) startup(ctx context.Context) { + a.ctx = ctx + runtime.LogInfo(ctx, "Application Startup called!") +} + +``` + +### Assets + +The _biggest_ change in v2 is how assets are handled. + +In v1, assets were passed via 2 application options: + +- `JS` - The application's JavaScript +- `CSS` - The application's CSS + +This meant that the responsibility of generating a single JS and CSS file was on the developer. This essentially required the use of complicated packers such as webpack. + +In v2, Wails makes no assumptions about your frontend assets, just like a webserver. All of your application assets are passed to the application options as an `embed.FS`. + +**This means there is no requirement to bundle your assets, encode images as Base64 or attempt the dark art of bundler configuration to use custom fonts**. + +At startup, Wails will scan the given `embed.FS` for `index.html` and use its location as the root path for all the other application assets - just like a webserver would. + +Example: An application has the following project layout. All final assets are placed in the `frontend/dist` directory: + +```shell +. +├── build/ +├── frontend/ +│ └── dist/ +│ ├── index.html +│ ├── main.js +│ ├── main.css +│ └── logo.svg +├── main.go +└── wails.json +``` + +Those assets may be used by the application by simply creating an `embed.FS`: + +```go title="Assets Example" +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + err := wails.Run(&options.App{ + /* Other Options */ + AssetServer: &assetserver.Options{ + Assets: assets, + }, + }) +} +``` + +Of course, bundlers can be used if you wish to. The only requirement is to pass the final application assets directory to Wails using an `embed.FS` in the `Assets` key of the [application options](../reference/options.mdx#application-options). + +### Project Configuration + +In v1, the project configuration was stored in the `project.json` file in the project root. In v2, the project configuration is stored in the `wails.json` file in the project root. + +The format of the file is slightly different. Here is a comparison: + +

+ +| v1 | v2 | Notes | +| ------------------ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | name | | +| description | | Removed | +| author / name | author / name | | +| author / email | author / email | | +| version | version | | +| binaryname | outputfilename | Changed | +| frontend / dir | | Removed | +| frontend / install | frontend:install | Changed | +| frontend / build | frontend:build | Changed | +| frontend / bridge | | Removed | +| frontend / serve | | Removed | +| tags | | Removed | +| | wailsjsdir | The directory to generate wailsjs modules | +| | assetdir | The directory of the compiled frontend assets for `dev` mode. This is normally inferred and could be left empty. | +| | reloaddirs | Comma separated list of additional directories to watch for changes and to trigger reloads in `dev` mode. This is only needed for some more advanced asset configurations. | + +

diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx new file mode 100644 index 00000000000..4a3de2a61b5 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx @@ -0,0 +1,25 @@ +# Mouse Buttons + +The Wails runtime intercepts mouse clicks to determine whether a frameless window needs resizing or a window needs to be moved. It has been asked how to detect when a mouse click has occurred, because `window.onclick` doesn't report the mouse buttons correctly. The following code shows how to detect mouse clicks: + +```javascript +window.addEventListener("mousedown", handleMouseButtonDown); + +function handleMouseButtonDown(event) { + if (event.button === 0) { + // left mouse button + } else if (event.button === 1) { + // middle mouse button + } else if (event.button === 2) { + // right mouse button + } else if (event.button === 3) { + // back mouse button + } else if (event.button === 4) { + // forward mouse button + } else { + // other mouse button + } +} +``` + +Reference: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx new file mode 100644 index 00000000000..21f7875e389 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx @@ -0,0 +1,40 @@ +# Obfuscated Builds + +Wails includes support for obfuscating your application using [garble](https://github.com/burrowers/garble). + +To produce an obfuscated build, you can use the `-obfuscate` flag with the `wails build` command: + +```bash +wails build -obfuscated +``` + +To customise the obfuscation settings, you can use the `-garbleargs` flag: + +```bash +wails build -obfuscated -garbleargs "-literals -tiny -seed=myrandomseed" +``` + +These settings may be persisted in your [project config](../reference/project-config). + +## How it works + +In a standard build, all bound methods are available in the frontend under the `window.go` variable. When these methods are called, the corresponding backend method is called using the fully qualified function name. When using an obfuscated build, methods are bound using an ID instead of a name. The bindings generated in the `wailsjs` directory use these IDs to call the backend functions. + +:::note + +To ensure that your application will work in obfuscated mode, you must use the generated bindings under the `wailsjs` directory in your application. + +::: + +## Example + +Importing the "Greet" method from the bindings like this: + +```js +import { Greet } from "../../wailsjs/go/main/App"; + +// snip +Greet("World"); +``` + +will ensure that the method will work correctly in obfuscated mode, as the bindings will be regenerated with IDs and the call mechanism updated. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx new file mode 100644 index 00000000000..e94cfbb7e77 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx @@ -0,0 +1,10 @@ +# 오버스크롤(Overscroll) + +[Overscroll](https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior) 은 페이지의 콘텐츠 경계를 넘어 스크롤할 때 가끔 발생하는 "바운스 효과"입니다. 이것은 모바일 앱에서도 동일합니다. CSS를 사용하여 비활성 할 수 있습니다. + +```css +html { + height: 100%; + overflow: hidden; +} +``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx new file mode 100644 index 00000000000..ce176943ea5 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx @@ -0,0 +1,47 @@ +# Routing + +Routing is a popular way to switch views in an application. This page offers some guidance around how to do that. + +## Vue + +The recommended approach for routing in Vue is [Hash Mode](https://next.router.vuejs.org/guide/essentials/history-mode.html#hash-mode): + +```js +import { createRouter, createWebHashHistory } from "vue-router"; + +const router = createRouter({ + history: createWebHashHistory(), + routes: [ + //... + ], +}); +``` + +## Angular + +The recommended approach for routing in Angular is [HashLocationStrategy](https://codecraft.tv/courses/angular/routing/routing-strategies#_hashlocationstrategy): + +```ts +RouterModule.forRoot(routes, { useHash: true }); +``` + +## React + +The recommended approach for routing in React is [HashRouter](https://reactrouter.com/en/main/router-components/hash-router): + +```jsx +import { HashRouter } from "react-router-dom"; + +ReactDOM.render( + + {/* The rest of your app goes here */} + + } exact /> + } /> + } /> + {/* more... */} + + , + root +); +``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx new file mode 100644 index 00000000000..4c7cf45ba99 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx @@ -0,0 +1,387 @@ +# Code Signing + +This is a guide on how you can sign your binaries generated with Wails on MacOS and Windows. The guide will target CI environments, more specifically GitHub Actions. + +## Windows + +First off you need a code signing certificate. If you do not already have one, Microsoft's info page lists some providers [here](https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/get-a-code-signing-certificate). Please note that an EV certificate is not required unless you need to write kernel-level software such as device drivers. For signing your Wails app, a standard code signing certificate will do just fine. + +It may be a good idea to check with your certificate provider how to sign your binaries on your local machine before targeting automated build systems, just so you know if there are any special requirements. For instance, [here](https://www.ssl.com/how-to/using-your-code-signing-certificate/) is SSL.com's code signing guide for Windows. If you know how to sign locally, it will be easier to troubleshoot any potential issues in a CI environment. For instance, SSL.com code signing certificates require the `/tr` flag for [SignTool.exe](https://docs.microsoft.com/en-us/windows/win32/seccrypto/signtool) while other providers may only need the `/t` flag for providing the timestamping server. Popular GitHub Actions for signing Windows binaries like [this one](https://github.com/Dana-Prajea/code-sign-action) does not support the `/tr` flag on SignTool.exe. Therefore this guide will focus on signing our app manually with PowerShell commands, but you can use actions like the [code-sign-action](https://github.com/Dana-Prajea/code-sign-action) Action if you prefer. + +First off, let's make sure we are able to build our Wails app in our GitHub CI. Here is a small workflow template: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend manually here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +Next we need to give the GitHub workflow access to our signing certificate. This is done by encoding your .pfx or .p12 certificate into a base64 string. To do this in PowerShell, you can use the following command assuming your certificate is called 'my-cert.p12': + +```PowerShell +certutil -encode .\my-cert.p12 my-cert-base64.txt +``` + +You should now have your .txt file with the base64 encoded certificate. It should start with _-----BEGIN CERTIFICATE-----_ and end with _-----END CERTIFICATE-----_. Now you need to make two action secrets on GitHub. Navigate to _Settings -> Secrets -> Actions_ and create the two following secrets: + +- **WIN_SIGNING_CERT** with the contents of your base64 encoded certificate text. +- **WIN_SIGNING_CERT_PASSWORD** with the contents of your certificate password. + +Now we're ready to implement the signing in our workflow using one of the two methods: + +### Method 1: signing with commands + +This method uses PowerShell commands to sign our app, and leaves you control over the entire signing process. + +After the `"Build Wails app"` step, we can add the following step to our workflow: + +```yaml +- name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd /t /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' + +``` + +This script creates a new directory for your certificate file, creates the certificate file from our base64 secret, converts it to a .pfx file, and finally signs the binary. The following variables needs to be replaced in the last line: + +- **signing algorithm**: usually sha256. +- **timestamping server**: URL to the timestamping server to use with your certificate. +- **path to binary**: path to the binary you want to sign. + +Given that our Wails config has `outputfilename` set to "app.exe" and that we have a certificate from SSL.com, this would be our workflow: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\app.exe + + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +### Method 2: automatically signing with Action + +It is possible to use a Windows code signing Action like [this](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate) one, but note it requires a SHA1 hash for the certificate and a certificate name. View an example of how to configure it on the Action's [marketplace](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate). + +--- + +## MacOS + +First off you need your code signing certificate from Apple. If you do not have one, a simple Google search will help you acquire one. Once you have your certificate, you need to export it and encode it to base64. [This tutorial](https://localazy.com/blog/how-to-automatically-sign-macos-apps-using-github-actions) shows you how to do that in an easy manner. Once you have exported your .p12 certificate file, you can encode it to base64 as seen in the tutorial with the following command: + +```bash +base64 Certificates.p12 | pbcopy +``` + +Now you're ready to create some GitHub project secrets, just as with Windows: + +- **APPLE_DEVELOPER_CERTIFICATE_P12_BASE64** with the contents of your newly copied base64 certificate. +- **APPLE_DEVELOPER_CERTIFICATE_PASSWORD** with the contents of your certificate password. +- **APPLE_PASSWORD** with the contents of an App-Specific password to your Apple-ID account which you can generate [here](https://appleid.apple.com/account/manage). + +Let's make sure we are able to build our Wails app in our GitHub Action workflow. Here is a small template: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +For code signing on macOS, [gon](https://github.com/mitchellh/gon) is a very handy tool for code signing and communicating with Apple servers, also written in Go, and will be used in this guide. + +After the `Build Wails app` step, add the following to the workflow: + +```yaml +- name: MacOS download gon for code signing and app notarization + if: matrix.platform == 'macos-latest' + run: | + brew install mitchellh/gon/gon +``` + +Now we need to configure some gon config files in our `build/darwin` directory: + +1. gon-sign.json: + +```json +{ + "source": ["./build/bin/app.app"], + "bundle_id": "app.myapp", + "apple_id": { + "username": "my-appleid@email.com", + "password": "@env:APPLE_PASSWORD" + }, + "sign": { + "application_identity": "Developer ID Application: My Name" + } +} +``` + +Where `source` is your Wails binary, `bundle_id` is your bundle ID, `apple_id` contains your Apple ID username and App-Specific password which you created earlier, and `sign.application_identity` is your identity which you can find by running the following command: + +```bash +security find-identity -v -p codesigning +``` + +2. entitlements.plist: + +```plist + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + + +``` + +In this file you configure the entitlements you need for you app, e.g. camera permissions if your app uses the camera. Read more about entitlements [here](https://developer.apple.com/documentation/bundleresources/entitlements). + +Make sure you have updated your `Info.plist` file with the same bundle ID as you entered in `gon-sign.json`. Here's an example `Info.plist` file: + +```plist + + + CFBundlePackageTypeAPPL + CFBundleNameMyApp + CFBundleExecutableapp + CFBundleIdentifierapp.myapp + CFBundleVersion0.1.0 + CFBundleGetInfoStringMy app is cool and nice and chill and + CFBundleShortVersionString0.1.0 + CFBundleIconFileiconfile + LSMinimumSystemVersion10.13.0 + NSHighResolutionCapabletrue + LSApplicationCategoryTypepublic.app-category.utilities + NSHumanReadableCopyright© Me + +``` + +Now we're ready to add the signing step in our workflow after building the Wails app: + +```yaml +- name: Import Code-Signing Certificates for macOS + if: matrix.platform == 'macos-latest' + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} +- name: Sign our macOS binary + if: matrix.platform == 'macos-latest' + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json +``` + +Please note that signing binaries with Apple could take anywhere from minutes to hours. + +## Combined workflow file: + +Here is our GitHub workflow file with Windows + macOS combined: + +```yaml +name: "example combined" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: MacOS download gon for code signing and app notarization + if: matrix.platform == 'macos-latest' + run: | + brew install mitchellh/gon/gon + - name: Import Code-Signing Certificates for macOS + if: matrix.platform == 'macos-latest' + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} + - name: Sign our macOS binary + if: matrix.platform == 'macos-latest' + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json + - name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\Monitor.exe + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +# End notes + +This guide inspired by the RiftShare project and its workflow, which is highly recommended to check out [here](https://github.com/achhabra2/riftshare/blob/main/.github/workflows/build.yaml). diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx new file mode 100644 index 00000000000..dc7706f8ffa --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx @@ -0,0 +1,81 @@ +# Single Instance Lock + +Single instance lock is a mechanism that allows you to prevent multiple instances of your app from running at the same time. +It is useful for apps that are designed to open files from the command line or from the OS file explorer. + +## Important + +Single Instance Lock does not implement a secure communications protocol between instances. When using single instance lock, +your app should treat any data passed to it from second instance callback as untrusted. +You should verify that args that you receive are valid and don't contain any malicious data. + +## How it works + +Windows: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via a shared window using [SendMessage](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage) +macOS: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via [NSDistributedNotificationCenter](https://developer.apple.com/documentation/foundation/nsdistributednotificationcenter) +Linux: Single instance lock is implemented using [dbus](https://www.freedesktop.org/wiki/Software/dbus/). The dbus name is generated from the unique id that you provide. Data is passed to the first instance via [dbus](https://www.freedesktop.org/wiki/Software/dbus/) + +## Usage + +When creating your app, you can enable single instance lock by passing a `SingleInstanceLock` struct to the `App` struct. +Use the `UniqueId` field to specify a unique id for your app. +This id is used to generate the mutex name on Windows and macOS and the dbus name on Linux. Use a UUID to ensure that the id is unique. +The `OnSecondInstanceLaunch` field is used to specify a callback that is called when a second instance of your app is launched. +The callback receives a `SecondInstanceData` struct that contains the command line arguments passed to the second instance and the working directory of the second instance. + +Note that OnSecondInstanceLaunch don't trigger windows focus. +You need to call `runtime.WindowUnminimise` and `runtime.Show` to bring your app to the front. +Note that on linux systems window managers may prevent your app from being brought to the front to avoid stealing focus. + +```go title="main.go" +var wailsContext *context.Context + +// NewApp creates a new App application struct +func NewApp() *App { + return &App{} +} + +// startup is called when the app starts. The context is saved +// so we can call the runtime methods +func (a *App) startup(ctx context.Context) { + wailsContext = &ctx +} + +func (a *App) onSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) { + secondInstanceArgs = secondInstanceData.Args + + println("user opened second instance", strings.Join(secondInstanceData.Args, ",")) + println("user opened second from", secondInstanceData.WorkingDirectory) + runtime.WindowUnminimise(*wailsContext) + runtime.Show(*wailsContext) + go runtime.EventsEmit(*wailsContext, "launchArgs", secondInstanceArgs) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + OnStartup: app.startup, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx new file mode 100644 index 00000000000..4651c422ed1 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx @@ -0,0 +1,153 @@ +# SvelteKit + +This guide will go into: + +1. Miminal Installation Steps - The steps needed to get a minimum Wails setup working for SvelteKit. +2. Install Script - Bash script for accomplishing the Minimal Installation Steps with optional Wails branding. +3. Important Notes - Issues that can be encountered when using SvelteKit + Wails and fixes. + +## 1. Minimal Installation Steps + +##### Install Wails for Svelte. + +- `wails init -n myapp -t svelte` + +##### Delete the svelte frontend. + +- Navigate into your newly created myapp folder. +- Delete the folder named "frontend" + +##### While in the Wails project root. Use your favorite package manager and install SvelteKit as the new frontend. Follow the prompts. + +- `npm create svelte@latest frontend` + +##### Modify wails.json. + +- Add `"wailsjsdir": "./frontend/src/lib",` Do note that this is where your Go and runtime functions will appear. +- Change your package manager frontend here if not using npm. + +##### Modify main.go. + +- The first comment `//go:embed all:frontend/dist` needs to be changed to `//go:embed all:frontend/build` + +##### Install/remove dependencies using your favorite package manager. + +- Navigate into your "frontend" folder. +- `npm i` +- `npm uninstall @sveltejs/adapter-auto` +- `npm i -D @sveltejs/adapter-static` + +##### Change adapter in svelte.config.js + +- First line of file change `import adapter from '@sveltejs/adapter-auto';` to `import adapter from '@sveltejs/adapter-static';` + +##### Put SvelteKit into SPA mode with prerendering. + +- Create a file under myapp/frontend/src/routes/ named +layout.ts/+layout.js. +- Add two lines into the newly created file `export const prerender = true` and `export const ssr = false` + +##### Test installation. + +- Navigate back into the Wails project root (one directory up). +- run `wails dev` +- If the application doesn't run please check through the previous steps. + +## 2. Install Script + +##### This Bash Script does the steps listed above. Make sure to read over the script and understand what the script is doing on your computer. + +- Create a file sveltekit-wails.sh +- Copy the below code into the new file then save it. +- Make it executable with `chmod +x sveltekit-wails.sh` +- Brand is an optional param below that adds back in the wails branding. Leave third param blank to not insert the Wails branding. +- Example usage: `./sveltekit-wails.sh pnpm newapp brand` + +##### sveltekit-wails.sh: + +``` +manager=$1 +project=$2 +brand=$3 +wails init -n $project -t svelte +cd $project +sed -i "s|npm|$manager|g" wails.json +sed -i 's|"auto",|"auto",\n "wailsjsdir": "./frontend/src/lib",|' wails.json +sed -i "s|all:frontend/dist|all:frontend/build|" main.go +if [[ -n $brand ]]; then + mv frontend/src/App.svelte +page.svelte + sed -i "s|'./assets|'\$lib/assets|" +page.svelte + sed -i "s|'../wails|'\$lib/wails|" +page.svelte + mv frontend/src/assets . +fi +rm -r frontend +$manager create svelte@latest frontend +if [[ -n $brand ]]; then + mv +page.svelte frontend/src/routes/+page.svelte + mkdir frontend/src/lib + mv assets frontend/src/lib/ +fi +cd frontend +$manager i +$manager uninstall @sveltejs/adapter-auto +$manager i -D @sveltejs/adapter-static +echo -e "export const prerender = true\nexport const ssr = false" > src/routes/+layout.ts +sed -i "s|-auto';|-static';|" svelte.config.js +cd .. +wails dev +``` + +## 3. Important Notes + +##### Server files will cause build failures. + +- \+layout.server.ts, +page.server.ts, +server.ts or any file with "server" in the name will fail to build as all routes are prerendered. + +##### The Wails runtime unloads with full page navigations! + +- Anything that causes full page navigations: `window.location.href = '//'` or Context menu reload when using wails dev. What this means is that you can end up losing the ability to call any runtime breaking the app. There are two ways to work around this. +- Use `import { goto } from '$app/navigation'` then call `goto('//')` in your +page.svelte. This will prevent a full page navigation. +- If full page navigation can't be prevented the Wails runtime can be added to all pages by adding the below into the `` of myapp/frontend/src/app.html + +``` + +... + + + +... + +``` + +See https://wails.io/docs/guides/frontend for more information. + +##### Inital data can be loaded and refreshed from +page.ts/+page.js to +page.svelte. + +- \+page.ts/+page.js works well with load() https://kit.svelte.dev/docs/load#page-data +- invalidateAll() in +page.svelte will call load() from +page.ts/+page.js https://kit.svelte.dev/docs/load#rerunning-load-functions-manual-invalidation. + +##### Error Handling + +- Expected errors using Throw error works in +page.ts/+page.js with a +error.svelte page. https://kit.svelte.dev/docs/errors#expected-errors +- Unexpected errors will cause the application to become unusable. Only recovery option (known so far) from unexpected errors is to reload the app. To do this create a file myapp/frontend/src/hooks.client.ts then add the below code to the file. + +``` +import { WindowReloadApp } from '$lib/wailsjs/runtime/runtime' +export async function handleError() { + WindowReloadApp() +} +``` + +##### Using Forms and handling functions + +- The simplest way is to call a function from the form is the standard, bind:value your variables and prevent submission `` +- The more advanced way is to use:enhance (progressive enhancement) which will allow for convenient access to formData, formElement, submitter. The important note is to always cancel() the form which prevents server side behavior. https://kit.svelte.dev/docs/form-actions#progressive-enhancement Example: + +``` + { + cancel() + console.log(Object.fromEntries(formData)) + console.log(formElement) + console.log(submitter) + handle() +}}> +``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx new file mode 100644 index 00000000000..790e3107f04 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx @@ -0,0 +1,97 @@ +# Templates + +Wails generates projects from pre-created templates. In v1, this was a difficult to maintain set of projects that were subject to going out of date. In v2, to empower the community, a couple of new features have been added for templates: + +- Ability to generate projects from [Remote Templates](../reference/cli.mdx#remote-templates) +- Tooling to help create your own templates + +## Creating Templates + +To create a template, you can use the `wails generate template` command. To generate a default template, run: + +`wails generate template -name mytemplate` + +This creates the directory "mytemplate" with default files: + +```shell title=mytemplate/ +. +|-- NEXTSTEPS.md +|-- README.md +|-- app.tmpl.go +|-- frontend +| `-- dist +| |-- assets +| | |-- fonts +| | | |-- OFL.txt +| | | `-- nunito-v16-latin-regular.woff2 +| | `-- images +| | `-- logo-dark.svg +| |-- index.html +| |-- main.css +| `-- main.js +|-- go.mod.tmpl +|-- main.tmpl.go +|-- template.json +`-- wails.tmpl.json +``` + +### Template Overview + +The default template consists of the following files and directories: + +| Filename / Dir | Description | +| --------------- | -------------------------------------------- | +| NEXTSTEPS.md | Instructions on how to complete the template | +| README.md | The README published with the template | +| app.tmpl.go | `app.go` template file | +| frontend/ | The directory containing frontend assets | +| go.mod.tmpl | `go.mod` template file | +| main.tmpl.go | `main.go` template file | +| template.json | The template metadata | +| wails.tmpl.json | `wails.json` template file | + +At this point it is advisable to follow the steps in `NEXTSTEPS.md`. + +## Creating a Template from an Existing Project + +It's possible to create a template from an existing frontend project by passing the path to the project when generating the template. We will now walk through how to create a Vue 3 template: + +- Install the vue cli: `npm install -g @vue/cli` +- Create the default project: `vue create vue3-base` + - Select `Default (Vue 3) ([Vue 3] babel, eslint)` +- After the project has been generated, run: + +```shell +> wails generate template -name wails-vue3-template -frontend .\vue3-base\ +Extracting base template files... +Migrating existing project files to frontend directory... +Updating package.json data... +Renaming package.json -> package.tmpl.json... +Updating package-lock.json data... +Renaming package-lock.json -> package-lock.tmpl.json... +``` + +- The template may now be customised as specified in the `NEXTSTEPS.md` file +- Once the files are ready, it can be tested by running: `wails init -n my-vue3-project -t .\wails-vue3-template\` +- To test the new project, run: `cd my-vue3-project` then `wails build` +- Once the project has compiled, run it: `.\build\bin\my-vue3-project.exe` +- You should have a fully functioning Vue3 application: + +```mdx-code-block +
+ +
+``` + +## Publishing Templates + +Publishing a template is simply pushing the files to GitHub. The following best practice is encouraged: + +- Remove any unwanted files and directories (such as `.git`) from your frontend directory +- Ensure that `template.json` is complete, especially `helpurl` +- Push the files to GitHub +- Create a PR on the [Community Templates](../community/templates.mdx) page +- Announce the template on the [Template Announcement](https://github.com/wailsapp/wails/discussions/825) discussion board diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx new file mode 100644 index 00000000000..2b5b7a25840 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx @@ -0,0 +1,368 @@ +# Troubleshooting + +An assortment of troubleshooting tips. + +## `wails` 명령어를 찾을 수 없나요? + +시스템에서 `wails` 명령어를 찾을 수 없는 경우 Go 설치 지침을 잘 따라했는지 확인해보세요. Normally, it means that the `go/bin` directory in your User's home directory is not in the `PATH` environment variable. You will also normally need to close and reopen any open command prompts so that changes to the environment made by the installer are reflected at the command prompt. + +## My application is displaying a white/blank screen + +Check that your application includes the assets from the correct directory. In your `main.go` file, you will have something similar to the following code: + +```go +//go:embed all:frontend/dist +var assets embed.FS +``` + +Check that `frontend/dist` contains your application assets. + +### Mac + +If this happens on Mac, try adding the following to your `Info.plist`: + +```xml +NSAppTransportSecurity + + NSAllowsLocalNetworking + + +``` + +Reference: https://github.com/wailsapp/wails/issues/1504#issuecomment-1174317433 + +## Mac application not valid + +If your built application looks like this in finder: + +```mdx-code-block +

+ +

+``` + +it's likely that your application's `info.plist` is invalid. Update the file in `build/.app/Contents/info.plist` and check if the data is valid, EG check the binary name is correct. To persist the changes, copy the file back to the `build/darwin` directory. + +## My application is not displaying the correct icon in Windows Explorer + +If your application is not displaying the correct icon, try deleting the hidden `IconCache.db` file located in the `C:\Users\<your username>\AppData\Local` directory. This will force Windows to rebuild the icon cache. + +Source: https://github.com/wailsapp/wails/issues/2360#issuecomment-1556070036 + +## Cannot call backend method from frontend with variadic arguments + +If you have a backend method defined with variadic parameters, eg: + +```go +func (a *App) TestFunc(msg string, args ...interface{}) error { + // Code +} +``` + +calling this method from the frontend like this will fail: + +```js +var msg = "Hello: "; +var args = ["Go", "JS"]; +window.go.main.App.TestFunc(msg, ...args) + .then((result) => { + //do things here + }) + .catch((error) => { + //handle error + }); +``` + +Workaround: + +```js +var msg = "Hello "; +var args = ["Go", "JS"]; +window.go.main.App.TestFunc(msg, args) + .then((result) => { + //without the 3 dots + //do things here + }) + .catch((error) => { + //handle error + }); +``` + +Credit: https://github.com/wailsapp/wails/issues/1186 + +## I'm having getting proxy errors when trying to install Wails + +If you are getting errors like this: + +``` +"https://proxy.golang.org/github.com/wailsapp/wails/cmd/wails/@v/list": dial tcp 172.217.163.49:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. +``` + +it's probably because the official Go Proxy is being blocked (Users in China have reported this). The solution is to set up the proxy manually, eg: + +``` +go env -w GO111MODULE=on +go env -w GOPROXY=https://goproxy.cn,direct +``` + +Source: https://github.com/wailsapp/wails/issues/1233 + +## The generated TypeScript doesn't have the correct types + +Sometimes the generated TypeScript doesn't have the correct types. To mitigate this, it is possible to specify what types should be generated using the `ts_type` struct tag. For more details, please read [this](https://github.com/tkrajina/typescriptify-golang-structs#custom-types). + +## When I navigate away from `index.html`, I am unable to call methods on the frontend + +If you navigate away from `index.html` to a new html file, the context will be lost. This can be fixed by adding the following imports to the `` section of any new page you navigate to: + +```html + + + + +``` + +Source: https://github.com/wailsapp/wails/discussions/1512 + +## I get `too many open files` errors on my Mac when I run `wails dev` + +By default, macOS will only allow you to open a maximum of 256 files. This can affect the `wails dev` command. This limit can be increased by running: `ulimit -n 1024` in the terminal. + +FSNotify is [looking to move to Apple's fsevents](https://github.com/fsnotify/fsnotify/issues/11) for Mac. If this isn't completed soon, we will create our own implementation, tracked [here](https://github.com/wailsapp/wails/issues/1733). + +## My Mac app gives me weird compilation errors + +A few users have reported seeing compilation errors such as the following: + +```shell +# github.com/wailsapp/wails/v2/internal/frontend/desktop/darwin +In file included from ../../pkg/mod/github.com/wailsapp/wails/v2@v2.0.0-beta.44.2/internal/frontend/desktop/darwin/callbacks.go:9: +In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:12: +/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSBundle.h:91:143: error: function does not return NSString +- (NSAttributedString *)localizedAttributedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName NS_FORMAT_ARGUMENT(1) NS_REFINED_FOR_SWIFT API_AVAILABLE(macos(12.0), ios(15.0), watchos(8.0), tvos(15.0)); + ~~~~~~~~~~~~~~ ^ ~ +/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:103:48: note: expanded from macro 'NS_FORMAT_ARGUMENT' + #define NS_FORMAT_ARGUMENT(A) __attribute__ ((format_arg(A))) +``` + +This is _normally_ due to a mismatch with the OS version you are running and the version of the XCode Command Line Tools installed. If you see an error like this, try upgrading your XCode Command Line Tools to the latest version. + +If reinstalling Xcode Command Tools still fails, you can check the path where the toolkit is located using: + +`xcode-select -p` + +If `/Applications/Xcode.app/Contents/Developer` is displayed, run `sudo xcode-select --switch /Library/Developer/CommandLineTools` + +Sources: https://github.com/wailsapp/wails/issues/1806 and https://github.com/wailsapp/wails/issues/1140#issuecomment-1290446496 + +## My application won't compile on Mac + +If you are getting errors like this: + +```shell +l1@m2 GoEasyDesigner % go build -tags dev -gcflags "all=-N -l" +/Users/l1/sdk/go1.20.5/pkg/tool/darwin_arm64/link: running clang failed: exit status 1 +Undefined symbols for architecture arm64: + "_OBJC_CLASS_$_UTType", referenced from: + objc-class-ref in 000016.o +ld: symbol(s) not found for architecture arm64 +clang: error: linker command failed with exit code 1 (use -v to see invocation) +``` +Ensure you have the latest SDK installed. If so and you're still experiencing this issue, try the following: + +```shell +export CGO_LDFLAGS="-framework UniformTypeIdentifiers" && go build -tags dev -gcflags "all=-N -l" +``` + +Sources: https://github.com/wailsapp/wails/pull/2925#issuecomment-1726828562 + + +-- + +## Cannot start service: Host version "x.x.x does not match binary version "x.x.x" + +It's preferable to add `frontend/node_modules` and `frontend/package-lock.json` to your `.gitignore`. Otherwise when opening your repository on another machine that may have different versions of Node installed, you may not be able to run your application. + +If this does happen, simply delete `frontend/node_modules` and `frontend/package-lock.json` and run your `wails build` or `wails dev` command again. + +## Build process stuck on "Generating bindings" + +Bindings generation process runs your application in a special mode. If application, intentionally or unintentionally, contains an endless loop (i.e. not exiting after `wails.Run()` finished), this can lead to build process stuck on the stage of bindings generation. Please make sure your code exits properly. + +## Mac application flashes white at startup + +This is due to the default background of the webview being white. If you want to use the window background colour instead, you can make the webview background transparent using the following config: + +```go + err := wails.Run(&options.App{ + Title: "macflash", + Width: 1024, + Height: 768, + // Other settings + Mac: &mac.Options{ + WebviewIsTransparent: true, + }, + }) +``` + +## I get a "Microsoft Edge can't read or write to its data directory" error when running my program as admin on Windows + +You set your program to require admin permissions and it worked great! Unfortunately, some users are seeing a "Microsoft Edge can't read or write to its data directory" error when running it. + +When a Windows machine has two local accounts: + +- Alice, an admin +- Bob, a regular user + +Bob sees a UAC prompt when running your program. Bob enters Alice's admin credentials into this prompt. The app launches with admin permissions under Alice's account. + +Wails instructs WebView2 to store user data at the specified `WebviewUserDataPath`. It defaults to `%APPDATA%\[BinaryName.exe]`. + +Because the application is running under Alice's account, `%APPDATA%\[BinaryName.exe]` resolves to `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`. + +WebView2 [creates some child processes under Bob's logged-in account instead of Alice's admin account](https://github.com/MicrosoftEdge/WebView2Feedback/issues/932#issue-807464179). Since Bob cannot access `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`, the "Microsoft Edge can't read or write to its data directory" error is shown. + +Possible solution #1: + +Refactor your application to work without constant admin permissions. If you just need to perform a small set of admin tasks (such as running an updater), you can run your application with the minimum permissions and then use the `runas` command to run these tasks with admin permissions as needed: + +```go +//go:build windows + +package sample + +import ( + "golang.org/x/sys/windows" + "syscall" +) + +// Calling RunAs("C:\path\to\my\updater.exe") shows Bob a UAC prompt. Bob enters Alice's admin credentials. The updater launches with admin permissions under Alice's account. +func RunAs(path string) error { + verbPtr, _ := syscall.UTF16PtrFromString("runas") + exePtr, _ := syscall.UTF16PtrFromString(path) + cwdPtr, _ := syscall.UTF16PtrFromString("") + argPtr, _ := syscall.UTF16PtrFromString("") + + var showCmd int32 = 1 //SW_NORMAL + + err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd) + if err != nil { + return err + } + return nil +} +``` + +Possible solution #2: + +Run your application with extended permissions. If you absolutely must run with constant admin permissions, WebView2 will function correctly if you use a data directory accessible by both users and you also launch your app with the `SeBackupPrivilege`, `SeDebugPrivilege`, and `SeRestorePrivilege` permissions. Here's an example: + +```go +package main + +import ( + "embed" + "os" + "runtime" + + "github.com/fourcorelabs/wintoken" + "github.com/hectane/go-acl" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +//go:embed all:frontend/dist +var assets embed.FS + +const ( + fixedTokenKey = "SAMPLE_RANDOM_KEY" + fixedTokenVal = "with-fixed-token" + webviewDir = "C:\\ProgramData\\Sample" +) + +func runWithFixedToken() { + println("Re-launching self") + token, err := wintoken.OpenProcessToken(0, wintoken.TokenPrimary) //pass 0 for own process + if err != nil { + panic(err) + } + defer token.Close() + + token.EnableTokenPrivileges([]string{ + "SeBackupPrivilege", + "SeDebugPrivilege", + "SeRestorePrivilege", + }) + + cmd := exec.Command(os.Args[0]) + cmd.Args = os.Args + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", fixedTokenKey, fixedTokenVal)) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.SysProcAttr = &syscall.SysProcAttr{Token: syscall.Token(token.Token())} + if err := cmd.Run(); err != nil { + println("Error after launching self:", err) + os.Exit(1) + } + println("Clean self launch :)") + os.Exit(0) +} + +func main() { + if runtime.GOOS == "windows" && os.Getenv(fixedTokenKey) != fixedTokenVal { + runWithFixedToken() + } + + println("Setting data dir to", webviewDir) + if err := os.MkdirAll(webviewDir, os.ModePerm); err != nil { + println("Failed creating dir:", err) + } + if err := acl.Chmod(webviewDir, 0777); err != nil { + println("Failed setting ACL on dir:", err) + } + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "sample-data-dir", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + Windows: &windows.Options{ + WebviewUserDataPath: webviewDir, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +If you use a data directory accessible by both users but not the extended privileges, you will receive a WebView2 `80010108 The object invoked has disconnected from its clients` error. + +Possible future solution #3: [run WebView2 using an in-memory mode if implemented](https://github.com/MicrosoftEdge/WebView2Feedback/issues/3637#issuecomment-1728300982). + +## WebView2 installation succeeded, but the wails doctor command shows that it is not installed + +If you have installed WebView2, but the `wails doctor` command shows that it is not installed, it is likely that the WebView2 runtime installed was for a different architecture. You can download the correct runtime from [here](https://developer.microsoft.com/en-us/microsoft-edge/webview2/). + +Source: https://github.com/wailsapp/wails/issues/2917 + +## WebVie2wProcess failed with kind + +If your Windows app generates this kind of error, you can check out what the error means [here](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2processfailedkind?view=webview2-winrt-1.0.2045.28). + diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx new file mode 100644 index 00000000000..ed258656d63 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx @@ -0,0 +1,82 @@ + +# Visual Studio Code + +This page is for miscellaneous tips and tricks when using Visual Studio Code with Wails. + +## Vetur Configuration + +Many thanks to [@Lyimmi](https://github.com/Lyimmi) for this tip. Originally posted [here](https://github.com/wailsapp/wails/issues/1791#issuecomment-1228158349). + +Vetur is a popular plugin for Visual Studio Code that provides syntax highlighting and code completion for Vue projects. When loading a Wails project in VSCode, Vetur will throw an error as it is expecting to find the frontend project in the root directory. To fix this, you can do the following: + +Create a file named `vetur.config.js` in the project's root. + +```javascript +// vetur.config.js +/** @type {import('vls').VeturConfig} */ +module.exports = { + // **optional** default: `{}` + // override vscode settings + // Notice: It only affects the settings used by Vetur. + settings: { + "vetur.useWorkspaceDependencies": true, + "vetur.experimental.templateInterpolationService": true + }, + // **optional** default: `[{ root: './' }]` + // support monorepos + projects: [ + { + // **required** + // Where is your project? + // It is relative to `vetur.config.js`. + // root: './packages/repo1', + root: './frontend', + // **optional** default: `'package.json'` + // Where is `package.json` in the project? + // We use it to determine the version of vue. + // It is relative to root property. + package: './package.json', + // **optional** + // Where is TypeScript config file in the project? + // It is relative to root property. + tsconfig: './tsconfig.json', + // **optional** default: `'./.vscode/vetur/snippets'` + // Where is vetur custom snippets folders? + snippetFolder: './.vscode/vetur/snippets', + // **optional** default: `[]` + // Register globally Vue component glob. + // If you set it, you can get completion by that components. + // It is relative to root property. + // Notice: It won't actually do it. You need to use `require.context` or `Vue.component` + globalComponents: [ + './src/components/**/*.vue' + ] + } + ] +} +``` + +Next, configure `frontend/tsconfig.json`: + +```javascript +{ + "compilerOptions": { + "module": "system", + "noImplicitAny": true, + "removeComments": true, + "preserveConstEnums": true, + "sourceMap": true, + "outFile": "../../built/local/tsc.js", + "allowJs": true + }, + "exclude": [ + "node_modules", + "**/*.spec.ts" + ], + "include": [ + "src/**/*", + "wailsjs/**/*.ts" + ] +} +``` +This should enable you to now use Vetur as expected. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx new file mode 100644 index 00000000000..22d3aec7078 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx @@ -0,0 +1,58 @@ +# NSIS installer + +```mdx-code-block +

+ +
+

+``` + +Wails는 [NSIS installer](https://nsis.sourceforge.io/)를 사용하여 Windows 인스톨러 생성을 지원합니다. + +## NSIS 설치하기 + +### Windows + +인스톨러는 [NSIS Download](https://nsis.sourceforge.io/Download) 페이지에서 사용이 가능합니다. + +만약 chocolatey 패키지 매니저를 사용한다면, 다음 스크립트를 실행하세요: + +``` +choco install nsis +``` + +만약 NSIS를 수동으로 설치하기 원한다면, NSIS가 설치된 경로에서 `makensis.exe`가 포함된 _Bin_ 폴더를 추가 해야합니다. [여기](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/) Windows에서 어떻게 경로를 추가하는지에 대한 튜토리얼이 있습니다. + +### Linux + +`nsis` 패키지는 사용자의 배포판 패키지 매니저를 통해 이용이 가능합니다. + +### MacOS + +NSIS는 homebrew를 통해 설치가 가능합니다: `brew install nsis`. + +## 인스톨러 생성하기 + +새로운 프로젝트가 생성되었을때, Wails는 NSIS 설정 파일을 `build/windows/installer`에 생성합니다. 설정 데이터는 `installer/info.json`로 부터 읽어오며 이 데이터는 이 프로젝트의 `wails.json` Info 섹션에서 설정되어 사용됩니다: + +```json +// ... + "Info": { + "companyName": "My Company Name", + "productName": "Wails Vite", + "productVersion": "1.0.0", + "copyright": "Copyright.........", + "comments": "Built using Wails (https://wails.io)" + }, +``` + +애플리케이션을 위한 인스톨러를 생성하기 위해 `-nsis` 플래그를 `wails build`와 함께 사용하세요: + +``` +wails build -nsis +``` + +이제 인스톨러는 `build/bin` 디렉토리에서 이용이 가능합니다. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx new file mode 100644 index 00000000000..821808c0b8d --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx @@ -0,0 +1,61 @@ +# Windows + +This page has miscellaneous guides related to developing Wails applications for Windows. + +## Handling the WebView2 Runtime Dependency + +Wails applications built for Windows have a runtime requirement on the Microsoft [WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/). Windows 11 will have this installed by default, but some machines won't. Wails offers an easy approach to dealing with this dependency. + +By using the `-webview2` flag when building, you can decide what your application will do when a suitable runtime is not detected (including if the installed runtime is too old). The four options are: + +1. Download +2. Embed +3. Browser +4. Error + +### Download + +This option will prompt the user that no suitable runtime has been found and then offer to download and run the official bootstrapper from Microsoft's WebView2 site. If the user proceeds, the official bootstrapper will be downloaded and run. + +### Embed + +This option embeds the official bootstrapper within the application. If no suitable runtime has been found, the application will offer to run the bootstrapper. This adds ~150k to the binary size. + +### Browser + +This option will prompt the user that no suitable runtime has been found and then offer to open a browser to the official WebView2 page where the bootstrapper can be downloaded and installed. The application will then exit, leaving the installation up to the user. + +### Error + +If no suitable runtime is found, an error is given to the user and no further action taken. + +## Fixed version runtime + +Another way of dealing with webview2 dependency is shipping it yourself. You can download [fixed version runtime](https://developer.microsoft.com/microsoft-edge/webview2/#download-section) and bundle or download it with your application. + +Also, you should specify path to fixed version of webview2 runtime in the `windows.Options` structure when launching wails. + +```go + wails.Run(&options.App{ + Windows: &windows.Options{ + WebviewBrowserPath: "", + }, + }) +``` + +Note: When `WebviewBrowserPath` is specified, `error` strategy will be forced in case of minimal required version mismatch or invalid path to a runtime. + +## Spawning other programs + +When spawning other programs, such as scripts, you will see the window appear on the screen. To hide the window, you can use the following code: + +```go +cmd := exec.Command("your_script.exe") +cmd.SysProcAttr = &syscall.SysProcAttr{ + HideWindow: true, + CreationFlags: 0x08000000, +} +cmd.Start() +``` + +Solution provided by [sithembiso](https://github.com/sithembiso) on the [discussions board](https://github.com/wailsapp/wails/discussions/1734#discussioncomment-3386172). diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx new file mode 100644 index 00000000000..44fa130cc74 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx @@ -0,0 +1,369 @@ +--- +sidebar_position: 20 +--- + +# How does it work? + +A Wails application is a standard Go application, with a webkit frontend. The Go part of the application consists of the application code and a runtime library that provides a number of useful operations, like controlling the application window. The frontend is a webkit window that will display the frontend assets. Also available to the frontend is a JavaScript version of the runtime library. Finally, it is possible to bind Go methods to the frontend, and these will appear as JavaScript methods that can be called, just as if they were local JavaScript methods. + +```mdx-code-block +
+ +
+``` + +## The Main Application + +### Overview + +The main application consists of a single call to `wails.Run()`. It accepts the application configuration which describes the size of the application window, the window title, what assets to use, etc. A basic application might look like this: + +```go title="main.go" +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + + app := &App{} + + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + + +type App struct { + ctx context.Context +} + +func (b *App) startup(ctx context.Context) { + b.ctx = ctx +} + +func (b *App) shutdown(ctx context.Context) {} + +func (b *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +### Options rundown + +This example has the following options set: + +- `Title` - The text that should appear in the window's title bar +- `Width` & `Height` - The dimensions of the window +- `Assets` - The application's frontend assets +- `OnStartup` - A callback for when the window is created and is about to start loading the frontend assets +- `OnShutdown` - A callback for when the application is about to quit +- `Bind` - A slice of struct instances that we wish to expose to the frontend + +A full list of application options can be found in the [Options Reference](reference/options). + +#### Assets + +The `Assets` option is mandatory as you can't have a Wails application without frontend assets. Those assets can be any files you would expect to find in a web application - html, js, css, svg, png, etc. **There is no requirement to generate asset bundles** - plain files will do. When the application starts, it will attempt to load `index.html` from your assets and the frontend will essentially work as a browser from that point on. It is worth noting that there is no requirement on where in the `embed.FS` the files live. It is likely that the embed path uses a nested directory relative to your main application code, such as `frontend/dist`: + +```go title="main.go" +//go:embed all:frontend/dist +var assets embed.FS +``` + +At startup, Wails will iterate the embedded files looking for the directory containing `index.html`. All other assets will be loaded relative to this directory. + +As production binaries use the files contained in `embed.FS`, there are no external files required to be shipped with the application. + +When running in development mode using the `wails dev` command, the assets are loaded off disk, and any changes result in a "live reload". The location of the assets will be inferred from the `embed.FS`. + +More details can be found in the [Application Development Guide](guides/application-development.mdx). + +#### Application Lifecycle Callbacks + +Just before the frontend is about to load `index.html`, a callback is made to the function provided in [OnStartup](reference/options.mdx#onstartup). A standard Go context is passed to this method. This context is required when calling the runtime so a standard pattern is to save a reference to in this method. Just before the application shuts down, the [OnShutdown](reference/options.mdx#onshutdown) callback is called in the same way, again with the context. There is also an [OnDomReady](reference/options.mdx#ondomready) callback for when the frontend has completed loading all assets in `index.html` and is equivalent of the [`body onload`](https://www.w3schools.com/jsref/event_onload.asp) event in JavaScript. It is also possible to hook into the window close (or application quit) event by setting the option [OnBeforeClose](reference/options.mdx#onbeforeclose). + +#### Method Binding + +The `Bind` option is one of the most important options in a Wails application. It specifies which struct methods to expose to the frontend. Think of structs like "controllers" in a traditional web application. When the application starts, it examines the struct instances listed in the `Bind` field in the options, determines which methods are public (starts with an uppercase letter) and will generate JavaScript versions of those methods that can be called by the frontend code. + +:::info Note + +Wails requires that you pass in an _instance_ of the struct for it to bind it correctly + +::: + +In this example, we create a new `App` instance and then add this instance to the `Bind` option in `wails.Run`: + +```go {17,27} title="main.go" +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + + app := &App{} + + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + + +type App struct { + ctx context.Context +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +You may bind as many structs as you like. Just make sure you create an instance of it and pass it in `Bind`: + +```go {10-12} + //... + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + &mystruct1{}, + &mystruct2{}, + }, + }) + +``` + +When you run `wails dev` (or `wails generate module`), a frontend module will be generated containing the following: + +- JavaScript bindings for all bound methods +- TypeScript declarations for all bound methods +- TypeScript definitions for all Go structs used as inputs or outputs by the bound methods + +This makes it incredibly simple to call Go code from the frontend, using the same strongly typed datastructures. + +## The Frontend + +### Overview + +The frontend is a collection of files rendered by webkit. It's like a browser and webserver in one. There is virtually[^1] no limit to which frameworks or libraries you can use. The main points of interaction between the frontend and your Go code are: + +- Calling bound Go methods +- Calling runtime methods + +### Calling bound Go methods + +When you run your application with `wails dev`, it will automatically generate JavaScript bindings for your structs in a directory called `wailsjs/go` (You can also do this by running `wails generate module`). The generated files mirror the package names in your application. In the example above, we bind `app`, which has one public method `Greet`. This will lead to the generation of the following files: + +```bash +wailsjs + └─go + └─main + ├─App.d.ts + └─App.js +``` + +Here we can see that there is a `main` package that contains the JavaScript bindings for the bound `App` struct, as well as the TypeScript declaration file for those methods. To call `Greet` from our frontend, we simply import the method and call it like a regular JavaScript function: + +```javascript +// ... +import { Greet } from "../wailsjs/go/main/App"; + +function doGreeting(name) { + Greet(name).then((result) => { + // Do something with result + }); +} +``` + +The TypeScript declaration file gives you the correct types for the bound methods: + +```ts +export function Greet(arg1: string): Promise; +``` + +The generated methods return a Promise. A successful call will result in the first return value from the Go call to be passed to the `resolve` handler. An unsuccessful call is when a Go method that has an error type as it's second return value, passes an error instance back to the caller. This is passed back via the `reject` handler. In the example above, `Greet` only returns a `string` so the JavaScript call will never reject - unless invalid data is passed to it. + +All data types are correctly translated between Go and JavaScript. Even structs. If you return a struct from a Go call, it will be returned to your frontend as a JavaScript class. + +:::info Note + +Struct fields _must_ have a valid `json` tag to be included in the generated TypeScript. + +Anonymous nested structs are not supported at this time. + +::: + +It is possible to send structs back to Go. Any JavaScript map/class passed as an argument that is expecting a struct, will be converted to that struct type. To make this process a lot easier, in `dev` mode, a TypeScript module is generated, defining all the struct types used in bound methods. Using this module, it's possible to construct and send native JavaScript objects to the Go code. + +There is also support for Go methods that use structs in their signature. All Go structs specified by a bound method (either as parameters or return types) will have TypeScript versions auto generated as part of the Go code wrapper module. Using these, it's possible to share the same data model between Go and JavaScript. + +Example: We update our `Greet` method to accept a `Person` instead of a string: + +```go title="main.go" +type Person struct { + Name string `json:"name"` + Age uint8 `json:"age"` + Address *Address `json:"address"` +} + +type Address struct { + Street string `json:"street"` + Postcode string `json:"postcode"` +} + +func (a *App) Greet(p Person) string { + return fmt.Sprintf("Hello %s (Age: %d)!", p.Name, p.Age) +} +``` + +The `wailsjs/go/main/App.js` file will still have the following code: + +```js title="App.js" +export function Greet(arg1) { + return window["go"]["main"]["App"]["Greet"](arg1); +} +``` + +But the `wailsjs/go/main/App.d.ts` file will be updated with the following code: + +```ts title="App.d.ts" +import { main } from "../models"; + +export function Greet(arg1: main.Person): Promise; +``` + +As we can see, the "main" namespace is imported from a new "models.ts" file. This file contains all the struct definitions used by our bound methods. In this example, this is a `Person` struct. If we look at `models.ts`, we can see how the models are defined: + +```ts title="models.ts" +export namespace main { + export class Address { + street: string; + postcode: string; + + static createFrom(source: any = {}) { + return new Address(source); + } + + constructor(source: any = {}) { + if ("string" === typeof source) source = JSON.parse(source); + this.street = source["street"]; + this.postcode = source["postcode"]; + } + } + export class Person { + name: string; + age: number; + address?: Address; + + static createFrom(source: any = {}) { + return new Person(source); + } + + constructor(source: any = {}) { + if ("string" === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.age = source["age"]; + this.address = this.convertValues(source["address"], Address); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice) { + return (a as any[]).map((elem) => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } +} +``` + +So long as you have TypeScript as part of your frontend build configuration, you can use these models in the following way: + +```js title="mycode.js" +import { Greet } from "../wailsjs/go/main/App"; +import { main } from "../wailsjs/go/models"; + +function generate() { + let person = new main.Person(); + person.name = "Peter"; + person.age = 27; + Greet(person).then((result) => { + console.log(result); + }); +} +``` + +The combination of generated bindings and TypeScript models makes for a powerful development environment. + +More information on Binding can be found in the [Binding Methods](guides/application-development.mdx#binding-methods) section of the [Application Development Guide](guides/application-development.mdx). + +### Calling runtime methods + +The JavaScript runtime is located at `window.runtime` and contains many methods to do various tasks such as emit an event or perform logging operations: + +```js title="mycode.js" +window.runtime.EventsEmit("my-event", 1); +``` + +More details about the JS runtime can be found in the [Runtime Reference](reference/runtime/intro). + +[^1]: There is a very small subset of libraries that use features unsupported in WebViews. There are often alternatives and workarounds for such cases. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx new file mode 100644 index 00000000000..9fd585e11f8 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx @@ -0,0 +1,75 @@ +--- +sidebar_position: 1 +--- + +# 소개 + +Wails is a project that enables you to write desktop apps using Go and web technologies. + +Consider it a lightweight and fast Electron alternative for Go. You can easily build applications with the flexibility and power of Go, combined with a rich, modern frontend. + +### Features + +- Native Menus, Dialogs, Theming and Translucency +- Windows, macOS and linux support +- Built in templates for Svelte, React, Preact, Vue, Lit and Vanilla JS +- Easily call Go methods from JavaScript +- Automatic Go struct to TypeScript model generation +- No CGO or external DLLs required on Windows +- Live development mode using the power of [Vite](https://vitejs.dev/) +- Powerful CLI to easily Create, Build and Package applications +- A rich [runtime library](/docs/reference/runtime/intro) +- Applications built with Wails are Apple & Microsoft Store compliant + +This is [varly](https://varly.app) - a desktop application for MacOS & Windows written using Wails. Not only does it look great, it uses native menus and translucency - everything you'd expect from a modern native app. + +```mdx-code-block +

+ + + +

+``` + +### Quick Start Templates + +Wails comes with a number of pre-configured templates that allow you to get your application up and running quickly. There are templates for the following frameworks: Svelte, React, Vue, Preact, Lit and Vanilla. There are both JavaScript and TypeScript versions for each template. + +### Native Elements + +Wails uses a purpose built library for handling native elements such as Window, Menus, Dialogs, etc, so you can build good-looking, feature rich desktop applications. + +**It does not embed a browser**, so it delivers a small runtime. Instead, it reuses the native rendering engine for the platform. On Windows, this is the new Microsoft Webview2 library, built on Chromium. + +### Go & JavaScript Interoperability + +Wails automatically makes your Go methods available to JavaScript, so you can call them by name from your frontend! It even generates TypeScript models for the structs used by your Go methods, so you can pass the same data structures between Go and JavaScript. + +### Runtime Library + +Wails provides a runtime library, for both Go and JavaScript, that handles a lot of the things modern applications need, like Eventing, Logging, Dialogs, etc. + +### Live Development Experience + +#### Automatic Rebuilds + +When you run your application in "dev" mode, Wails will build your application as a native desktop application, but will read your assets from disk. It will detect any changes to your Go code and automatically rebuild and relaunch your application. + +#### Automatic Reloads + +When changes to your application assets are detected, your running application will "reload", reflecting your changes almost immediately. + +#### Develop your application in a Browser + +If you prefer to debug and develop in a browser then Wails has you covered. The running application also has a webserver that will run your application in any browser that connects to it. It will even refresh when your assets change on disk. + +### Production-ready Native Binaries + +When you're ready to do the final build of your application, the CLI will compile it down to a single executable, with all the assets bundled into it. On Windows and MacOS, it is possible to create a native package for distribution. The assets used in packaging (icon, info.plist, manifest file, etc) are part of your project and may be customised, giving you total control over how your applications are built. + +### Tooling + +The Wails CLI provides a hassle-free way to generate, build and bundle your applications. It will do the heavy lifting of creating icons, compiling your application with optimal settings and delivering a distributable, production ready binary. Choose from a number of starter templates to get up and running quickly! diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx new file mode 100644 index 00000000000..c7aea10a64d --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx @@ -0,0 +1,240 @@ +--- +sidebar_position: 2 +--- + +# CLI + +The Wails CLI has a number of commands that are used for managing your projects. All commands are run in the following way: + +`wails ` + +## init + +`wails init` is used for generating projects. + +| Flag | Description | Default | +|:------------------ |:----------------------------------------------------------------------------------------------------------------------- |:-------------------:| +| -n "project name" | Name of the project. **Mandatory**. | | +| -d "project dir" | Project directory to create | Name of the project | +| -g | Initialise git repository | | +| -l | List available project templates | | +| -q | Suppress output to console | | +| -t "template name" | The project template to use. This can be the name of a default template or a URL to a remote template hosted on github. | vanilla | +| -ide | Generate IDE project files | | +| -f | Force build application | false | + +Example: `wails init -n test -d mytestproject -g -ide vscode -q` + +This will generate a a project called "test" in the "mytestproject" directory, initialise git, generate vscode project files and do so silently. + +More information on using IDEs with Wails can be found [here](../guides/ides.mdx). + +### Remote Templates + +Remote templates (hosted on GitHub) are supported and can be installed by using the template's project URL. + +Example: `wails init -n test -t https://github.com/leaanthony/testtemplate[@v1.0.0]` + +A list of community maintained templates can be found [here](../community/templates.mdx) + +:::warning Attention + +**The Wails project does not maintain, is not responsible nor liable for 3rd party templates!** + +If you are unsure about a template, inspect `package.json` and `wails.json` for what scripts are run and what packages are installed. + +::: + +## build + +`wails build` is used for compiling your project to a production-ready binary. + +| Flag | Description | Default | +|:-------------------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |:--------------------------------------------------------------------------------------------------------------------------------------------------- | +| -clean | Cleans the `build/bin` directory | | +| -compiler "compiler" | Use a different go compiler to build, eg go1.15beta1 | go | +| -debug | Retains debug information in the application and shows the debug console. Allows the use of the devtools in the application window | | +| -devtools | Allows the use of the devtools in the application window in production (when -debug is not used). Ctrl/Cmd+Shift+F12 may be used to open the devtools window. *NOTE*: This option will make your application FAIL Mac appstore guidelines. Use for debugging only. | | +| -dryrun | Prints the build command without executing it | | +| -f | Force build application | | +| -garbleargs | Arguments to pass to garble | `-literals -tiny -seed=random` | +| -ldflags "flags" | Additional ldflags to pass to the compiler | | +| -m | Skip mod tidy before compile | | +| -nopackage | Do not package application | | +| -nocolour | Disable colour in output | | +| -nosyncgomod | Do not sync go.mod with the Wails version | | +| -nsis | Generate NSIS installer for Windows | | +| -o filename | Output filename | | +| -obfuscated | Obfuscate the application using [garble](https://github.com/burrowers/garble) | | +| -platform | Build for the given (comma delimited) [platforms](../reference/cli.mdx#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | platform = `GOOS` environment variable if given else `runtime.GOOS`.
arch = `GOARCH` envrionment variable if given else `runtime.GOARCH`. | +| -race | Build with Go's race detector | | +| -s | Skip building the frontend | | +| -skipbindings | Skip bindings generation | | +| -tags "extra tags" | Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated | | +| -trimpath | Remove all file system paths from the resulting executable. | | +| -u | Updates your project's `go.mod` to use the same version of Wails as the CLI | | +| -upx | Compress final binary using "upx" | | +| -upxflags | Flags to pass to upx | | +| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 | +| -webview2 | WebView2 installer strategy: download,embed,browser,error | download | +| -windowsconsole | Keep the console window for Windows builds | | + +For a detailed description of the `webview2` flag, please refer to the [Windows](../guides/windows.mdx) Guide. + +If you prefer to build using standard Go tooling, please consult the [Manual Builds](../guides/manual-builds.mdx) guide. + +Example: + +`wails build -clean -o myproject.exe` + +:::info + +On Mac, the application will be bundled with `Info.plist`, not `Info.dev.plist`. + +::: + +:::info UPX on Apple Silicon + +There are [issues](https://github.com/upx/upx/issues/446) with using UPX with Apple Silicon. + +::: + +:::info UPX on Windows + +Some Antivirus vendors false positively mark `upx` compressed binaries as virus, see [issue](https://github.com/upx/upx/issues/437). + +::: + +### Platforms + +Supported platforms are: + +| Platform | Description | +|:---------------- |:--------------------------------------------- | +| darwin | MacOS + architecture of build machine | +| darwin/amd64 | MacOS 10.13+ AMD64 | +| darwin/arm64 | MacOS 11.0+ ARM64 | +| darwin/universal | MacOS AMD64+ARM64 universal application | +| windows | Windows 10/11 + architecture of build machine | +| windows/amd64 | Windows 10/11 AMD64 | +| windows/arm64 | Windows 10/11 ARM64 | +| linux | Linux + architecture of build machine | +| linux/amd64 | Linux AMD64 | +| linux/arm64 | Linux ARM64 | + +## doctor + +`wails doctor` will run diagnostics to ensure that your system is ready for development. + +Example: + +``` +Wails CLI v2.0.0-beta + +Scanning system - Please wait (this may take a long time)...Done. + +System +------ +OS: Windows 10 Pro +Version: 2009 (Build: 19043) +ID: 21H1 +Go Version: go1.18 +Platform: windows +Architecture: amd64 + +Dependency Package Name Status Version +---------- ------------ ------ ------- +WebView2 N/A Installed 93.0.961.52 +npm N/A Installed 6.14.15 +*upx N/A Installed upx 3.96 + +* - Optional Dependency + +Diagnosis +--------- +Your system is ready for Wails development! + +``` + +## dev + +`wails dev` is used to run your application in a "live development" mode. This means: + +- The application's `go.mod` will be updated to use the same version of Wails as the CLI +- The application is compiled and run automatically +- A watcher is started and will trigger a rebuild of your dev app if it detects changes to your go files +- A webserver is started on `http://localhost:34115` which serves your application (not just frontend) over http. This allows you to use your favourite browser development extensions +- All application assets are loaded from disk. If they are changed, the application will automatically reload (not rebuild). All connected browsers will also reload +- A JS module is generated that provides the following: +- JavaScript wrappers of your Go methods with autogenerated JSDoc, providing code hinting +- TypeScript versions of your Go structs, that can be constructed and passed to your go methods +- A second JS module is generated that provides a wrapper + TS declaration for the runtime +- On macOS, it will bundle the application into a `.app` file and run it. It will use a `build/darwin/Info.dev.plist` for development. + +| Flag | Description | Default | +|:---------------------------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |:--------------------- | +| -appargs "args" | Arguments passed to the application in shell style | | +| -assetdir "./path/to/assets" | Serve assets from the given directory instead of using the provided asset FS | Value in `wails.json` | +| -browser | Opens a browser to `http://localhost:34115` on startup | | +| -compiler "compiler" | Use a different go compiler to build, eg go1.15beta1 | go | +| -debounce | The time to wait for reload after an asset change is detected | 100 (milliseconds) | +| -devserver "host:port" | The address to bind the wails dev server to | "localhost:34115" | +| -extensions | Extensions to trigger rebuilds (comma separated) | go | +| -forcebuild | Force build of application | | +| -frontenddevserverurl "url" | Use 3rd party dev server url to serve assets, EG Vite | "" | +| -ldflags "flags" | Additional ldflags to pass to the compiler | | +| -loglevel "loglevel" | Loglevel to use - Trace, Debug, Info, Warning, Error | Debug | +| -nocolour | Turn off colour cli output | false | +| -noreload | Disable automatic reload when assets change | | +| -nosyncgomod | Do not sync go.mod with the Wails version | false | +| -race | Build with Go's race detector | false | +| -reloaddirs | Additional directories to trigger reloads (comma separated) | Value in `wails.json` | +| -s | Skip building the frontend | false | +| -save | Saves the given `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce`, `devserver` and `frontenddevserverurl` flags in `wails.json` to become the defaults for subsequent invocations. | | +| -skipbindings | Skip bindings generation | | +| -tags "extra tags" | Build tags to pass to compiler (quoted and space separated) | | +| -v | Verbosity level (0 - silent, 1 - standard, 2 - verbose) | 1 | +| -wailsjsdir | The directory to generate the generated Wails JS modules | Value in `wails.json` | + +Example: + +`wails dev -assetdir ./frontend/dist -wailsjsdir ./frontend/src -browser` + +This command will do the following: + +- Build the application and run it (more details [here](../guides/manual-builds.mdx) +- Generate the Wails JS modules in `./frontend/src` +- Watch for updates to files in `./frontend/dist` and reload on any change +- Open a browser and connect to the application + +There is more information on using this feature with existing framework scripts [here](../guides/application-development.mdx#live-reloading). + +## generate + +### template + +Wails uses templates for project generation. The `wails generate template` command helps scaffold a template so that it may be used for generating projects. + +| Flag | Description | +|:---------------- |:------------------------------------------- | +| -name | The template name (Mandatory) | +| -frontend "path" | Path to frontend project to use in template | + +For more details on creating templates, consult the [Templates guide](../guides/templates.mdx). + +### module + +The `wails generate module` command allows you to manually generate the `wailsjs` directory for your application. + +## update + +`wails update` will update the version of the Wails CLI. + +| Flag | Description | +|:------------------ |:------------------------------------- | +| -pre | Update to latest pre-release version | +| -version "version" | Install a specific version of the CLI | + +## version + +`wails version` will simply output the current CLI version. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx new file mode 100644 index 00000000000..ff9a2442281 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx @@ -0,0 +1,230 @@ +--- +sidebar_position: 4 +--- + +# Menus + +It is possible to add an application menu to Wails projects. This is achieved by defining a [Menu](#menu) struct and setting it in the [`Menu`](../reference/options.mdx#menu) application config, or by calling the runtime method [MenuSetApplicationMenu](../reference/runtime/menu.mdx#menusetapplicationmenu). + +An example of how to create a menu: + +```go + + app := NewApp() + + AppMenu := menu.NewMenu() + FileMenu := AppMenu.AddSubmenu("File") + FileMenu.AddText("&Open", keys.CmdOrCtrl("o"), openFile) + FileMenu.AddSeparator() + FileMenu.AddText("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) { + runtime.Quit(app.ctx) + }) + + if runtime.GOOS == "darwin" { + AppMenu.Append(menu.EditMenu()) // on macos platform, we should append EditMenu to enable Cmd+C,Cmd+V,Cmd+Z... shortcut + } + + err := wails.Run(&options.App{ + Title: "Menus Demo", + Width: 800, + Height: 600, + Menu: AppMenu, // reference the menu above + Bind: []interface{}{ + app, + }, + ) + // ... +``` + +It is also possible to dynamically update the menu, by updating the menu struct and calling [MenuUpdateApplicationMenu](../reference/runtime/menu.mdx#menuupdateapplicationmenu). + +The example above uses helper methods, however it's possible to build the menu structs manually. + +## Menu + +A Menu is a collection of MenuItems: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +type Menu struct { + Items []*MenuItem +} +``` + +For the Application menu, each MenuItem represents a single menu such as "Edit". + +A simple helper method is provided for building menus: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func NewMenuFromItems(first *MenuItem, rest ...*MenuItem) *Menu +``` + +This makes the layout of the code more like that of a menu without the need to add the menu items manually after creating them. Alternatively, you can just create the menu items and add them to the menu manually. + +## MenuItem + +A MenuItem represents an item within a Menu. + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +// MenuItem represents a menu item contained in a menu +type MenuItem struct { + Label string + Role Role + Accelerator *keys.Accelerator + Type Type + Disabled bool + Hidden bool + Checked bool + SubMenu *Menu + Click Callback +} +``` + +| Field | Type | Notes | +| ----------- | ------------------------------------ | ------------------------------------------------------------- | +| Label | string | The menu text | +| Accelerator | [\*keys.Accelerator](#accelerator) | Key binding for this menu item | +| Type | [Type](#type) | Type of MenuItem | +| Disabled | bool | Disables the menu item | +| Hidden | bool | Hides this menu item | +| Checked | bool | Adds check to item (Checkbox & Radio types) | +| SubMenu | [\*Menu](#menu) | Sets the submenu | +| Click | [Callback](#callback) | Callback function when menu clicked | +| Role | string | Defines a [role](#role) for this menu item. Mac only for now. | + +### Accelerator + +Accelerators (sometimes called keyboard shortcuts) define a binding between a keystroke and a menu item. Wails defines an Accelerator as a combination or key + [Modifier](#modifier). They are available in the `"github.com/wailsapp/wails/v2/pkg/menu/keys"` package. + +Example: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines cmd+o on Mac and ctrl-o on Window/Linux + myShortcut := keys.CmdOrCtrl("o") +``` + +Keys are any single character on a keyboard with the exception of `+`, which is defined as `plus`. Some keys cannot be represented as characters so there are a set of named characters that may be used: + +| | | | | +|:-----------:|:-----:|:-----:|:---------:| +| `backspace` | `f1` | `f16` | `f31` | +| `tab` | `f2` | `f17` | `f32` | +| `return` | `f3` | `f18` | `f33` | +| `enter` | `f4` | `f19` | `f34` | +| `escape` | `f5` | `f20` | `f35` | +| `left` | `f6` | `f21` | `numlock` | +| `right` | `f7` | `f22` | | +| `up` | `f8` | `f23` | | +| `down` | `f9` | `f24` | | +| `space` | `f10` | `f25` | | +| `delete` | `f11` | `f36` | | +| `home` | `f12` | `f37` | | +| `end` | `f13` | `f38` | | +| `page up` | `f14` | `f39` | | +| `page down` | `f15` | `f30` | | + +Wails also supports parsing accelerators using the same syntax as Electron. This is useful for storing accelerators in config files. + +Example: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines cmd+o on Mac and ctrl-o on Window/Linux + myShortcut, err := keys.Parse("Ctrl+Option+A") +``` + +#### Modifier + +The following modifiers are keys that may be used in combination with the accelerator key: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" +const ( + // CmdOrCtrlKey represents Command on Mac and Control on other platforms + CmdOrCtrlKey Modifier = "cmdorctrl" + // OptionOrAltKey represents Option on Mac and Alt on other platforms + OptionOrAltKey Modifier = "optionoralt" + // ShiftKey represents the shift key on all systems + ShiftKey Modifier = "shift" + // ControlKey represents the control key on all systems + ControlKey Modifier = "ctrl" +) +``` + +A number of helper methods are available to create Accelerators using modifiers: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" +func CmdOrCtrl(key string) *Accelerator +func OptionOrAlt(key string) *Accelerator +func Shift(key string) *Accelerator +func Control(key string) *Accelerator +``` + +Modifiers can be combined using `keys.Combo(key string, modifier1 Modifier, modifier2 Modifier, rest ...Modifier)`: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines "Ctrl+Option+A" on Mac and "Ctrl+Alt+A" on Window/Linux + myShortcut := keys.Combo("a", ControlKey, OptionOrAltKey) +``` + +### Type + +Each menu item must have a type and there are 5 types available: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +const ( + TextType Type = "Text" + SeparatorType Type = "Separator" + SubmenuType Type = "Submenu" + CheckboxType Type = "Checkbox" + RadioType Type = "Radio" +) +``` + +For convenience, helper methods are provided to quickly create a menu item: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func Text(label string, accelerator *keys.Accelerator, click Callback) *MenuItem +func Separator() *MenuItem +func Radio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func Checkbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func SubMenu(label string, menu *Menu) *Menu +``` + +You can also create menu items directly on a menu by using the "Add" helpers: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func (m *Menu) AddText(label string, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddSeparator() *MenuItem +func (m *Menu) AddRadio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddCheckbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddSubMenu(label string, menu *Menu) *MenuI +``` + +A note on radio groups: A radio group is defined as a number of radio menu items that are next to each other in the menu. This means that you do not need to group items together as it is automatic. However, that also means you cannot have 2 radio groups next to each other - there must be a non-radio item between them. + +### Callback + +Each menu item may have a callback that is executed when the item is clicked: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +type Callback func(*CallbackData) + +type CallbackData struct { + MenuItem *MenuItem +} +``` + +The function is given a `CallbackData` struct which indicates which menu item triggered the callback. This is useful when using radio groups that may share a callback. + +### Role + +:::info Roles + +Roles are currently supported on Mac only. + +::: + +A menu item may have a role, which is essentially a pre-defined menu item. We currently support the following roles: + +| Role | Description | +| ------------ | ------------------------------------------------------------------------ | +| AppMenuRole | The standard Mac application menu. Can be created using `menu.AppMenu()` | +| EditMenuRole | The standard Mac edit menu. Can be created using `menu.EditMenu()` | diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx new file mode 100644 index 00000000000..46d1c071b60 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx @@ -0,0 +1,853 @@ +--- +sidebar_position: 3 +--- + +# Options + +## Application Options + +The `Options.App` struct contains the application configuration. It is passed to the `wails.Run()` method: + +```go title="Example" +import ( + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/linux" + "github.com/wailsapp/wails/v2/pkg/options/mac" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +func main() { + + err := wails.Run(&options.App{ + Title: "Menus Demo", + Width: 800, + Height: 600, + DisableResize: false, + Fullscreen: false, + WindowStartState: options.Maximised, + Frameless: true, + MinWidth: 400, + MinHeight: 400, + MaxWidth: 1280, + MaxHeight: 1024, + StartHidden: false, + HideWindowOnClose: false, + BackgroundColour: &options.RGBA{R: 0, G: 0, B: 0, A: 255}, + AlwaysOnTop: false, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: assetsHandler, + Middleware: assetsMidldeware, + }, + Menu: app.applicationMenu(), + Logger: nil, + LogLevel: logger.DEBUG, + LogLevelProduction: logger.ERROR, + OnStartup: app.startup, + OnDomReady: app.domready, + OnShutdown: app.shutdown, + OnBeforeClose: app.beforeClose, + CSSDragProperty: "--wails-draggable", + CSSDragValue: "drag", + EnableDefaultContextMenu: false, + EnableFraudulentWebsiteDetection: false, + ZoomFactor: 1.0, + IsZoomControlEnabled: false, + Bind: []interface{}{ + app, + }, + ErrorFormatter: func(err error) any { return err.Error() }, + Windows: &windows.Options{ + WebviewIsTransparent: false, + WindowIsTranslucent: false, + BackdropType: windows.Mica, + DisableWindowIcon: false, + DisableFramelessWindowDecorations: false, + WebviewUserDataPath: "", + WebviewBrowserPath: "", + Theme: windows.SystemDefault, + CustomTheme: &windows.ThemeSettings{ + DarkModeTitleBar: windows.RGB(20, 20, 20), + DarkModeTitleText: windows.RGB(200, 200, 200), + DarkModeBorder: windows.RGB(20, 0, 20), + LightModeTitleBar: windows.RGB(200, 200, 200), + LightModeTitleText: windows.RGB(20, 20, 20), + LightModeBorder: windows.RGB(200, 200, 200), + }, + // User messages that can be customised + Messages *windows.Messages + // OnSuspend is called when Windows enters low power mode + OnSuspend func() + // OnResume is called when Windows resumes from low power mode + OnResume func(), + WebviewGpuDisabled: false, + }, + Mac: &mac.Options{ + TitleBar: &mac.TitleBar{ + TitlebarAppearsTransparent: true, + HideTitle: false, + HideTitleBar: false, + FullSizeContent: false, + UseToolbar: false, + HideToolbarSeparator: true, + }, + Appearance: mac.NSAppearanceNameDarkAqua, + WebviewIsTransparent: true, + WindowIsTranslucent: false, + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + Linux: &linux.Options{ + Icon: icon, + WindowIsTranslucent: false, + WebviewGpuPolicy: linux.WebviewGpuPolicyAlways, + ProgramName: "wails" + }, + Debug: options.Debug{ + OpenInspectorOnStartup: false, + }, + }) + + if err != nil { + log.Fatal(err) + } +} + +``` + +### Title + +The text shown in the window's title bar. + +Name: Title
Type: `string` + +### Width + +The initial width of the window. + +Name: Width
Type: `int`
Default: 1024. + +### Height + +The initial height of the window. + +Name: Height
Type: `int`
Default: 768 + +### DisableResize + +By default, the main window is resizable. Setting this to `true` will keep it a fixed size. + +Name: DisableResize
Type: `bool` + +### Fullscreen + +Deprecated: Please use [WindowStartState](#windowstartstate). + +### WindowStartState + +Defines how the window should present itself at startup. + +| Value | Win | Mac | Lin | +| ---------- | --- | --- | --- | +| Fullscreen | ✅ | ✅ | ✅ | +| Maximised | ✅ | ✅ | ✅ | +| Minimised | ✅ | ❌ | ✅ | + +Name: WindowStartState
Type: `options.WindowStartState` + +### Frameless + +When set to `true`, the window will have no borders or title bar. Also see [Frameless Windows](../guides/frameless.mdx). + +Name: Frameless
Type: `bool` + +### MinWidth + +This sets the minimum width for the window. If the value given in `Width` is less than this value, the window will be set to `MinWidth` by default. + +Name: MinWidth
Type: `int` + +### MinHeight + +This sets the minimum height for the window. If the value given in `Height` is less than this value, the window will be set to `MinHeight` by default. + +Name: MinHeight
Type: `int` + +### MaxWidth + +This sets the maximum width for the window. If the value given in `Width` is more than this value, the window will be set to `MaxWidth` by default. + +Name: MaxWidth
Type: `int` + +### MaxHeight + +This sets the maximum height for the window. If the value given in `Height` is more than this value, the window will be set to `MaxHeight` by default. + +Name: MaxHeight
Type: `int` + +### StartHidden + +When set to `true`, the application will be hidden until [WindowShow](../reference/runtime/window.mdx#windowshow) is called. + +Name: StartHidden
Type: `bool` + +### HideWindowOnClose + +By default, closing the window will close the application. Setting this to `true` means closing the window will + +hide the window instead. + +Name: HideWindowOnClose
Type: `bool` + +### BackgroundColour + +This value is the default background colour of the window. Example: options.NewRGBA(255,0,0,128) - Red at 50% transparency + +Name: BackgroundColour
Type: `*options.RGBA`
Default: white + +### AlwaysOnTop + +Indicates that the window should stay above other windows when losing focus. + +Name: AlwaysOnTop
Type: `bool` + +### Assets + +Deprecated: Please use Assets on [AssetServer specific options](#assetserver). + +### AssetsHandler + +Deprecated: Please use AssetsHandler on [AssetServer specific options](#assetserver). + +### AssetServer + +This defines AssetServer specific options. It allows to customize the AssetServer with static assets, serving assets dynamically with an `http.Handler` or hook into the request chain with an `assetserver.Middleware`. + +Not all features of an `http.Request` are currently supported, please see the following feature matrix: + +| Feature | Win | Mac | Lin | +| ----------------------- | --- | --- | ------ | +| GET | ✅ | ✅ | ✅ | +| POST | ✅ | ✅ | ✅ [^1] | +| PUT | ✅ | ✅ | ✅ [^1] | +| PATCH | ✅ | ✅ | ✅ [^1] | +| DELETE | ✅ | ✅ | ✅ [^1] | +| Request Headers | ✅ | ✅ | ✅ [^1] | +| Request Body | ✅ | ✅ | ✅ [^2] | +| Request Body Streaming | ✅ | ✅ | ✅ [^2] | +| Response StatusCodes | ✅ | ✅ | ✅ [^1] | +| Response Headers | ✅ | ✅ | ✅ [^1] | +| Response Body | ✅ | ✅ | ✅ | +| Response Body Streaming | ❌ | ✅ | ✅ | +| WebSockets | ❌ | ❌ | ❌ | +| HTTP Redirects 30x | ✅ | ❌ | ❌ | + +Name: AssetServer
Type: `*assetserver.Options` + +#### Assets + +The static frontend assets to be used by the application. + +A GET request is first tried to be served from this `fs.FS`. If the `fs.FS` returns `os.ErrNotExist` for that file, the request handling will fallback to the [Handler](#handler) and tries to serve the GET request from it. + +If set to nil, all GET requests will be forwarded to [Handler](#handler). + +Name: Assets
Type: `fs.FS` + +#### Handler + +The assets handler is a generic `http.Handler` for fallback handling of assets that can't be found. + +The handler will be called for every GET request that can't be served from [Assets](#assets), due to `os.ErrNotExist`. Furthermore all non GET requests will always be served from this Handler. If not defined, the result is the following in cases where the Handler would have been called: + +- GET request: `http.StatusNotFound` +- Other request: `http.StatusMethodNotAllowed` + +NOTE: When used in combination with a Frontend DevServer there might be limitations, eg. Vite serves the index.html on every path, that does not contain a file extension. + +Name: AssetsHandler
Type: `http.Handler` + +#### Middleware + +Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default request handler dynamically, e.g. implement specialized Routing etc. The Middleware is called to build a new `http.Handler` used by the AssetSever and it also receives the default handler used by the AssetServer as an argument. + +If not defined, the default AssetServer request chain is executed. + +Name: Middleware
Type: `assetserver.Middleware` + +### Menu + +The menu to be used by the application. More details about Menus in the [Menu Reference](../reference/runtime/menu.mdx). + +:::note + +On Mac, if no menu is specified, a default menu will be created. + +::: + +Name: Menu
Type: `*menu.Menu` + +### Logger + +The logger to be used by the application. More details about logging in the [Log Reference](../reference/runtime/log.mdx). + +Name: Logger
Type: `logger.Logger`
Default: Logs to Stdout + +### LogLevel + +The default log level. More details about logging in the [Log Reference](../reference/runtime/log.mdx). + +Name: LogLevel
Type: `logger.LogLevel`
Default: `Info` in dev mode, `Error` in production mode + +### LogLevelProduction + +The default log level for production builds. More details about logging in the [Log Reference](../reference/runtime/log.mdx). + +Name: LogLevelProduction
Type: `logger.LogLevel`
Default: `Error` + +### OnStartup + +This callback is called after the frontend has been created, but before `index.html` has been loaded. It is given the application context. + +Name: OnStartup
Type: `func(ctx context.Context)` + +### OnDomReady + +This callback is called after the frontend has loaded `index.html` and its resources. It is given the application context. + +Name: OnDomReady
Type: `func(ctx context.Context)` + +### OnShutdown + +This callback is called after the frontend has been destroyed, just before the application terminates. It is given the application context. + +Name: OnShutdown
Type: `func(ctx context.Context)` + +### OnBeforeClose + +If this callback is set, it will be called when the application is about to quit, either by clicking the window close button or calling `runtime.Quit`. Returning true will cause the application to continue, false will continue shutdown as normal. This is good for confirming with the user that they wish to exit the program. + +Example: + +```go title=windowsapp.go +func (b *App) beforeClose(ctx context.Context) (prevent bool) { + dialog, err := runtime.MessageDialog(ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Quit?", + Message: "Are you sure you want to quit?", + }) + + if err != nil { + return false + } + return dialog != "Yes" +} +``` + +Name: OnBeforeClose
Type: `func(ctx context.Context) bool` + +### CSSDragProperty + +Indicates the CSS property to use to identify which elements can be used to drag the window. Default: `--wails-draggable`. + +Name: CSSDragProperty
Type: `string` + +### CSSDragValue + +Indicates what value the `CSSDragProperty` style should have to drag the window. Default: `drag`. + +Name: CSSDragValue
Type: `string` + +### EnableDefaultContextMenu + +EnableDefaultContextMenu enables the browser's default context-menu in production. + +By default, the browser's default context-menu is only available in development and in a `-debug` [build](../reference/cli.mdx#build) along with the devtools inspector, Using this option you can enable the default context-menu in `production` while the devtools inspector won't be available unless the `-devtools` build flag is used. + +When this option is enabled, by default the context-menu will only be shown for text contexts (where Cut/Copy/Paste is needed), to override this behavior, you can use the CSS property `--default-contextmenu` on any HTML element (including the `body`) with the following values : + +| CSS Style | Behavior | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--default-contextmenu: auto;` | (**default**) will show the default context menu only if :
contentEditable is true OR text has been selected OR element is input or textarea | +| `--default-contextmenu: show;` | will always show the default context menu | +| `--default-contextmenu: hide;` | will always hide the default context menu | + +This rule is inherited like any normal CSS rule, so nesting works as expected. + +:::note +This filtering functionality is only enabled in production, so in development and in debug build, the full context-menu is always available everywhere. +::: + +:::warning +This filtering functionality is NOT a security measure, the developer should expect that the full context-menu could be leaked anytime which could contain commands like (Download image, Reload, Save webpage), if this is a concern, the developer SHOULD NOT enable the default context-menu. +::: + + +Name: EnableDefaultContextMenu
Type: `bool` + +### EnableFraudulentWebsiteDetection + +EnableFraudulentWebsiteDetection enables scan services for fraudulent content, such as malware or phishing attempts. These services might send information from your app like URLs navigated to and possibly other content to cloud services of Apple and Microsoft. + +Name: EnableFraudulentWebsiteDetection
Type: `bool` + +### ZoomFactor + +Name: ZoomFactor
Type: `float64` + +This defines the zoom factor for the WebView2. This is the option matching the Edge user activated zoom in or out. + +### IsZoomControlEnabled + +Name: IsZoomControlEnabled
Type: `bool` + +This enables the zoom factor to be changed by the user. Please note that the zoom factor can be set in the options while disallowing the user to change it at runtime (f.e. for a kiosk application or similar). + +### Bind + +A slice of struct instances defining methods that need to be bound to the frontend. + +Name: Bind
Type: `[]interface{}` + +### ErrorFormatter + +A function that determines how errors are formatted when returned by a JS-to-Go method call. The returned value will be marshalled as JSON. + +Name: ErrorFormatter
Type: `func (error) any` + +### Windows + +This defines [Windows specific options](#windows). + +Name: Windows
Type: `*windows.Options` + +#### WebviewIsTransparent + +Setting this to `true` will make the webview background transparent when an alpha value of `0` is used. This means that if you use `rgba(0,0,0,0)` for `background-color` in your CSS, the host window will show through. Often combined with [WindowIsTranslucent](#WindowIsTranslucent) to make frosty-looking applications. + +Name: WebviewIsTransparent
Type: `bool` + +#### WindowIsTranslucent + +Setting this to `true` will make the window background translucent. Often combined with [WebviewIsTransparent](#WebviewIsTransparent). + +For Windows 11 versions before build 22621, this will use the [BlurBehind](https://learn.microsoft.com/en-us/windows/win32/dwm/blur-ovw) method for translucency, which can be slow. For Windows 11 versions after build 22621, this will enable the newer translucency types that are much faster. By default, the type of translucency used will be determined by Windows. To configure this, use the [BackdropType](#BackdropType) option. + +Name: WindowIsTranslucent
Type: `bool` + +#### BackdropType + +:::note + +Requires Windows 11 build 22621 or later. + +::: + +Sets the translucency type of the window. This is only applicable if [WindowIsTranslucent](#WindowIsTranslucent) is set to `true`. + +Name: BackdropType
Type `windows.BackdropType` + +The value can be one of the following: + +| Value | Description | +| ------- | ----------------------------------------------------------------------------------------- | +| Auto | Let Windows decide which backdrop to use | +| None | Do not use translucency | +| Acrylic | Use [Acrylic](https://learn.microsoft.com/en-us/windows/apps/design/style/acrylic) effect | +| Mica | Use [Mica](https://learn.microsoft.com/en-us/windows/apps/design/style/mica) effect | +| Tabbed | Use Tabbed. This is a backdrop that is similar to Mica. | + +#### DisableWindowIcon + +Setting this to `true` will remove the icon in the top left corner of the title bar. + +Name: DisableWindowIcon
Type: `bool` + +#### DisableFramelessWindowDecorations + +Setting this to `true` will remove the window decorations in [Frameless](#Frameless) mode. This means there will be no 'Aero Shadow' and no 'Rounded Corners' shown for the window. Please note that 'Rounded Corners' are only supported on Windows 11. + +Name: DisableFramelessWindowDecorations
Type: `bool` + +#### WebviewUserDataPath + +This defines the path where the WebView2 stores the user data. If empty `%APPDATA%\[BinaryName.exe]` will be used. + +Name: WebviewUserDataPath
Type: `string` + +#### WebviewBrowserPath + +This defines the path to a directory with WebView2 executable files and libraries. If empty, webview2 installed in the system will be used. + +Important information about distribution of fixed version runtime: + +- [How to get and extract runtime](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#details-about-the-fixed-version-runtime-distribution-mode) +- [Known issues for fixed version](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#known-issues-for-fixed-version) +- [The path of fixed version of the WebView2 Runtime should not contain \Edge\Application\.](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.1245.22#createcorewebview2environmentwithoptions) + +Name: WebviewBrowserPath
Type: `string` + +#### Theme + +Minimum Windows Version: Windows 10 2004/20H1 + +This defines the theme that the application should use: + +| Value | Description | +| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| SystemDefault | _Default_. The theme will be based on the system default. If the user changes their theme, the application will update to use the new setting | +| Dark | The application will use a dark theme exclusively | +| Light | The application will use a light theme exclusively | + +Name: Theme
Type: `windows.Theme` + +#### CustomTheme + +:::note + +Minimum Windows Version: Windows 10/11 2009/21H2 Build 22000 + +::: + +Allows you to specify custom colours for TitleBar, TitleText and Border for both light and dark mode, as well as when the window is active or inactive. + +Name: CustomTheme
Type: `windows.CustomTheme` + +##### CustomTheme type + +The CustomTheme struct uses `int32` to specify the colour values. These are in the standard(!) Windows format of: `0x00BBGGAA`. A helper function is provided to do RGB conversions into this format: `windows.RGB(r,g,b uint8)`. + +NOTE: Any value not provided will default to black. + +```go +type ThemeSettings struct { + DarkModeTitleBar int32 + DarkModeTitleBarInactive int32 + DarkModeTitleText int32 + DarkModeTitleTextInactive int32 + DarkModeBorder int32 + DarkModeBorderInactive int32 + LightModeTitleBar int32 + LightModeTitleBarInactive int32 + LightModeTitleText int32 + LightModeTitleTextInactive int32 + LightModeBorder int32 + LightModeBorderInactive int32 +} +``` + +Example: + +```go + CustomTheme: &windows.ThemeSettings{ + // Theme to use when window is active + DarkModeTitleBar: windows.RGB(255, 0, 0), // Red + DarkModeTitleText: windows.RGB(0, 255, 0), // Green + DarkModeBorder: windows.RGB(0, 0, 255), // Blue + LightModeTitleBar: windows.RGB(200, 200, 200), + LightModeTitleText: windows.RGB(20, 20, 20), + LightModeBorder: windows.RGB(200, 200, 200), + // Theme to use when window is inactive + DarkModeTitleBarInactive: windows.RGB(128, 0, 0), + DarkModeTitleTextInactive: windows.RGB(0, 128, 0), + DarkModeBorderInactive: windows.RGB(0, 0, 128), + LightModeTitleBarInactive: windows.RGB(100, 100, 100), + LightModeTitleTextInactive: windows.RGB(10, 10, 10), + LightModeBorderInactive: windows.RGB(100, 100, 100), + }, +``` + +#### Messages + +A struct of strings used by the webview2 installer if a valid webview2 runtime is not found. + +Name: Messages
Type: `*windows.Messages` + +Customise this for any language you choose to support. + +#### ResizeDebounceMS + +ResizeDebounceMS is the amount of time to debounce redraws of webview2 when resizing the window. The default value (0) will perform redraws as fast as it can. + +Name: ResizeDebounceMS
Type: `uint16` + +#### OnSuspend + +If set, this function will be called when Windows initiates a switch to low power mode (suspend/hibernate) + +Name: OnSuspend
Type: `func()` + +#### OnResume + +If set, this function will be called when Windows resumes from low power mode (suspend/hibernate) + +Name: OnResume
Type: `func()` + +#### WebviewGpuIsDisabled + +Setting this to `true` will disable GPU hardware acceleration for the webview. + +Name: WebviewGpuIsDisabled
Type: `bool` + +#### EnableSwipeGestures + +Setting this to `true` will enable swipe gestures for the webview. + +Name: EnableSwipeGestures
Type: `bool` + +### Mac + +This defines [Mac specific options](#mac). + +Name: Mac
Type: `*mac.Options` + +#### TitleBar + +The TitleBar struct provides the ability to configure the look and feel of the title bar. + +Name: TitleBar
Type: [`*mac.TitleBar`](#titlebar-struct) + +##### Titlebar struct + +The titlebar of the application can be customised by using the TitleBar options: + +```go +type TitleBar struct { + TitlebarAppearsTransparent bool + HideTitle bool + HideTitleBar bool + FullSizeContent bool + UseToolbar bool + HideToolbarSeparator bool +} +``` + +| Name | Description | +| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| TitlebarAppearsTransparent | Makes the titlebar transparent. This has the effect of hiding the titlebar and the content fill the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindow/1419167-titlebarappearstransparent?language=objc) | +| HideTitle | Hides the title of the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindowtitlevisibility?language=objc) | +| HideTitleBar | Removes [NSWindowStyleMaskTitled](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemasktitled/) from the style mask | +| FullSizeContent | Makes the webview fill the entire window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemaskfullsizecontentview) | +| UseToolbar | Adds a default toolbar to the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nstoolbar?language=objc) | +| HideToolbarSeparator | Removes the line beneath the toolbar. [Apple Docs](https://developer.apple.com/documentation/appkit/nstoolbar/1516954-showsbaselineseparator?language=objc) | + +Preconfigured titlebar settings are available: + +| Setting | Example | +| --------------------------- | ---------------------------------------------- | +| `mac.TitleBarDefault()` | ![](/img/reference/titlebar-default.webp) | +| `mac.TitleBarHidden()` | ![](/img/reference/titlebar-hidden.webp) | +| `mac.TitleBarHiddenInset()` | ![](/img/reference/titlebar-hidden-inset.webp) | + +Example: + +```go +Mac: &mac.Options{ + TitleBar: mac.TitleBarHiddenInset(), +} +``` + +Click [here](https://github.com/lukakerr/NSWindowStyles) for some inspiration on customising the titlebar. + +#### Appearance + +Appearance is used to set the style of your app in accordance with Apple's [NSAppearance](https://developer.apple.com/documentation/appkit/nsappearancename?language=objc) names. + +Name: Appearance
Type: [`mac.AppearanceType`](#appearance-type) + +##### Appearance type + +You can specify the application's [appearance](https://developer.apple.com/documentation/appkit/nsappearance?language=objc). + +| Value | Description | +| ----------------------------------------------------- | --------------------------------------------------------------- | +| DefaultAppearance | DefaultAppearance uses the default system value | +| NSAppearanceNameAqua | The standard light system appearance | +| NSAppearanceNameDarkAqua | The standard dark system appearance | +| NSAppearanceNameVibrantLight | The light vibrant appearance | +| NSAppearanceNameAccessibilityHighContrastAqua | A high-contrast version of the standard light system appearance | +| NSAppearanceNameAccessibilityHighContrastDarkAqua | A high-contrast version of the standard dark system appearance | +| NSAppearanceNameAccessibilityHighContrastVibrantLight | A high-contrast version of the light vibrant appearance | +| NSAppearanceNameAccessibilityHighContrastVibrantDark | A high-contrast version of the dark vibrant appearance | + +Example: + +```go +Mac: &mac.Options{ + Appearance: mac.NSAppearanceNameDarkAqua, +} +``` + +#### WebviewIsTransparent + +Setting this to `true` will make the webview background transparent when an alpha value of `0` is used. This means that if you use `rgba(0,0,0,0)` for `background-color` in your CSS, the host window will show through. Often combined with [WindowIsTranslucent](#WindowIsTranslucent) to make frosty-looking applications. + +Name: WebviewIsTransparent
Type: `bool` + +#### WindowIsTranslucent + +Setting this to `true` will make the window background translucent. Often combined with [WebviewIsTransparent](#WebviewIsTransparent) to make frosty-looking applications. + +Name: WindowIsTranslucent
Type: `bool` + +#### Preferences + +The Preferences struct provides the ability to configure the Webview preferences. + +Name: Preferences
Type: [`*mac.Preferences`](#preferences-struct) + +##### Preferences struct + +You can specify the webview preferences. + +```go +type Preferences struct { + TabFocusesLinks u.Bool + TextInteractionEnabled u.Bool + FullscreenEnabled u.Bool +} +``` + +| Name | Description | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| TabFocusesLinks | A Boolean value that indicates whether pressing the tab key changes the focus to links and form controls. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/2818595-tabfocuseslinks?language=objc) | +| TextInteractionEnabled | A Boolean value that indicates whether to allow people to select or otherwise interact with text. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3727362-textinteractionenabled?language=objc) | +| FullscreenEnabled | A Boolean value that indicates whether a web view can display content full screen. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3917769-elementfullscreenenabled?language=objc) | + +Example: + +```go +Mac: &mac.Options{ + Preferences: &mac.Preferences{ + TabFocusesLinks: mac.Enabled, + TextInteractionEnabled: mac.Disabled, + FullscreenEnabled: mac.Enabled, + } +} +``` + +#### About + +This configuration lets you set the title, message and icon for the "About" menu item in the app menu created by the "AppMenu" role. + +Name: About
Type: [`*mac.AboutInfo`](#about-struct) + +##### About struct + +```go + +type AboutInfo struct { + Title string + Message string + Icon []byte +} +``` + +If these settings are provided, an "About" menu item will appear in the app menu (when using the `AppMenu` role). Given this configuration: + +```go +//go:embed build/appicon.png +var icon []byte + +func main() { + err := wails.Run(&options.App{ + ... + Mac: &mac.Options{ + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + }) +``` + +The "About" menu item will appear in the app menu: + +```mdx-code-block +
+ +
+
+``` + +When clicked, that will open an about message box: + +```mdx-code-block +
+ +
+
+``` + +### Linux + +This defines [Linux specific options](#linux). + +Name: Linux
Type: `*linux.Options` + +#### Icon + +Sets up the icon representing the window. This icon is used when the window is minimized (also known as iconified). + +Name: Icon
Type: `[]byte` + +Some window managers or desktop environments may also place it in the window frame, or display it in other contexts. On others, the icon is not used at all, so your mileage may vary. + +NOTE: Gnome on Wayland at least does not display this icon. To have a application icon there, a `.desktop` file has to be used. On KDE it should work. + +The icon should be provided in whatever size it was naturally drawn; that is, don’t scale the image before passing it. Scaling is postponed until the last minute, when the desired final size is known, to allow best quality. + +#### WindowIsTranslucent + +Setting this to `true` will make the window background translucent. Some window managers may ignore it, or result in a black window. + +Name: WindowIsTranslucent
Type: `bool` + +#### WebviewGpuPolicy + +This option is used for determining the webview's hardware acceleration policy. + +Name: WebviewGpuPolicy
Type: [`options.WebviewGpuPolicy`](#webviewgpupolicy-type)
Default: `WebviewGpuPolicyAlways` + +##### WebviewGpuPolicy type + +| Value | Description | +| ------------------------ | -------------------------------------------------------------------- | +| WebviewGpuPolicyAlways | Hardware acceleration is always enabled | +| WebviewGpuPolicyOnDemand | Hardware acceleration is enabled/disabled as request by web contents | +| WebviewGpuPolicyNever | Hardware acceleration is always disabled | + +#### ProgramName + +This option is used to set the program's name for the window manager via GTK's g_set_prgname(). This name should not be localized, [see the docs](https://docs.gtk.org/glib/func.set_prgname.html). + +When a .desktop file is created this value helps with window grouping and desktop icons when the .desktop file's `Name` property differs form the executable's filename. + +Name: ProgramName
Type: string
+ +### Debug + +This defines [Debug specific options](#Debug) that apply to debug builds. + +Name: Debug
Type: `options.Debug` + +#### OpenInspectorOnStartup + +Setting this to `true` will open the WebInspector on startup of the application. + +Name: OpenInspectorOnStartup
Type: `bool` + +[^1]: This requires WebKit2GTK 2.36+ support and your app needs to be build with the build tag `webkit2_36` to activate support for this feature. This also bumps the minimum requirement of WebKit2GTK to 2.36 for your app. +[^2]: This requires WebKit2GTK 2.40+ support and your app needs to be build with the build tag `webkit2_40` to activate support for this feature. This also bumps the minimum requirement of WebKit2GTK to 2.40 for your app. diff --git a/website/versioned_docs/version-v2.6.0/reference/project-config.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/project-config.mdx rename to website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx new file mode 100644 index 00000000000..b8eef677b92 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx @@ -0,0 +1,13 @@ +--- +sidebar_position: 7 +--- + +# 브라우저 + +이 메소드들은 시스템 브라우저와 관련 있습니다. + +### BrowserOpenURL + +시스템 브라우저에서 URL을 엽니다. + +Go: `BrowserOpenURL(ctx context.Context, url string)`
JS: `BrowserOpenURL(url string)` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx new file mode 100644 index 00000000000..805f68ed917 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx @@ -0,0 +1,23 @@ +--- +sidebar_position: 8 +--- + +# Clipboard + +This part of the runtime provides access to the operating system's clipboard.
The current implementation only handles text. + +### ClipboardGetText + +This method reads the currently stored text from the clipboard. + +Go: `ClipboardGetText(ctx context.Context) (string, error)`
Returns: a string (if the clipboard is empty an empty string will be returned) or an error. + +JS: `ClipboardGetText(): Promise`
Returns: a promise with a string result (if the clipboard is empty an empty string will be returned). + +### ClipboardSetText + +This method writes a text to the clipboard. + +Go: `ClipboardSetText(ctx context.Context, text string) error`
Returns: an error if there is any. + +JS: `ClipboardSetText(text: string): Promise`
Returns: a promise with true result if the text was successfully set on the clipboard, false otherwise. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx new file mode 100644 index 00000000000..9b3e6cf145c --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx @@ -0,0 +1,302 @@ +--- +sidebar_position: 5 +--- + +# Dialog + +This part of the runtime provides access to native dialogs, such as File Selectors and Message boxes. + +:::info JavaScript + +Dialog is currently unsupported in the JS runtime. + +::: + +### OpenDirectoryDialog + +Opens a dialog that prompts the user to select a directory. Can be customised using [OpenDialogOptions](#opendialogoptions). + +Go: `OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)` + +Returns: Selected directory (blank if the user cancelled) or an error + +### OpenFileDialog + +Opens a dialog that prompts the user to select a file. Can be customised using [OpenDialogOptions](#opendialogoptions). + +Go: `OpenFileDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)` + +Returns: Selected file (blank if the user cancelled) or an error + +### OpenMultipleFilesDialog + +Opens a dialog that prompts the user to select multiple files. Can be customised using [OpenDialogOptions](#opendialogoptions). + +Go: `OpenMultipleFilesDialog(ctx context.Context, dialogOptions OpenDialogOptions) ([]string, error)` + +Returns: Selected files (nil if the user cancelled) or an error + +### SaveFileDialog + +Opens a dialog that prompts the user to select a filename for the purposes of saving. Can be customised using [SaveDialogOptions](#savedialogoptions). + +Go: `SaveFileDialog(ctx context.Context, dialogOptions SaveDialogOptions) (string, error)` + +Returns: The selected file (blank if the user cancelled) or an error + +### MessageDialog + +Displays a message using a message dialog. Can be customised using [MessageDialogOptions](#messagedialogoptions). + +Go: `MessageDialog(ctx context.Context, dialogOptions MessageDialogOptions) (string, error)` + +Returns: The text of the selected button or an error + +## Options + +### OpenDialogOptions + +```go +type OpenDialogOptions struct { + DefaultDirectory string + DefaultFilename string + Title string + Filters []FileFilter + ShowHiddenFiles bool + CanCreateDirectories bool + ResolvesAliases bool + TreatPackagesAsDirectories bool +} +``` + +| Field | Description | Win | Mac | Lin | +| -------------------------- | ---------------------------------------------- | --- | --- | --- | +| DefaultDirectory | The directory the dialog will show when opened | ✅ | ✅ | ✅ | +| DefaultFilename | The default filename | ✅ | ✅ | ✅ | +| Title | Title for the dialog | ✅ | ✅ | ✅ | +| [Filters](#filefilter) | A list of file filters | ✅ | ✅ | ✅ | +| ShowHiddenFiles | Show files hidden by the system | | ✅ | ✅ | +| CanCreateDirectories | Allow user to create directories | | ✅ | | +| ResolvesAliases | If true, returns the file not the alias | | ✅ | | +| TreatPackagesAsDirectories | Allow navigating into packages | | ✅ | | + +### SaveDialogOptions + +```go +type SaveDialogOptions struct { + DefaultDirectory string + DefaultFilename string + Title string + Filters []FileFilter + ShowHiddenFiles bool + CanCreateDirectories bool + TreatPackagesAsDirectories bool +} +``` + +| Field | Description | Win | Mac | Lin | +| -------------------------- | ---------------------------------------------- | --- | --- | --- | +| DefaultDirectory | The directory the dialog will show when opened | ✅ | ✅ | ✅ | +| DefaultFilename | The default filename | ✅ | ✅ | ✅ | +| Title | Title for the dialog | ✅ | ✅ | ✅ | +| [Filters](#filefilter) | A list of file filters | ✅ | ✅ | ✅ | +| ShowHiddenFiles | Show files hidden by the system | | ✅ | ✅ | +| CanCreateDirectories | Allow user to create directories | | ✅ | | +| TreatPackagesAsDirectories | Allow navigating into packages | | ✅ | | + +### MessageDialogOptions + +```go +type MessageDialogOptions struct { + Type DialogType + Title string + Message string + Buttons []string + DefaultButton string + CancelButton string +} +``` + +| Field | Description | Win | Mac | Lin | +| ------------- | -------------------------------------------------------------------------- | -------------- | --- | --- | +| Type | The type of message dialog, eg question, info... | ✅ | ✅ | ✅ | +| Title | Title for the dialog | ✅ | ✅ | ✅ | +| Message | The message to show the user | ✅ | ✅ | ✅ | +| Buttons | A list of button titles | | ✅ | | +| DefaultButton | The button with this text should be treated as default. Bound to `return`. | ✅[*](#windows) | ✅ | | +| CancelButton | The button with this text should be treated as cancel. Bound to `escape` | | ✅ | | + +#### Windows + +Windows has standard dialog types in which the buttons are not customisable. The value returned will be one of: "Ok", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No", "Try Again" or "Continue". + +For Question dialogs, the default button is "Yes" and the cancel button is "No". This can be changed by setting the `DefaultButton` value to `"No"`. + +Example: +```go + result, err := runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Question", + Message: "Do you want to continue?", + DefaultButton: "No", + }) +``` + +#### Linux + +Linux has standard dialog types in which the buttons are not customisable. The value returned will be one of: "Ok", "Cancel", "Yes", "No" + +#### Mac + +A message dialog on Mac may specify up to 4 buttons. If no `DefaultButton` or `CancelButton` is given, the first button is considered default and is bound to the `return` key. + +For the following code: + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, +}) +``` + +the first button is shown as default: + +```mdx-code-block +
+ +
+
+``` + +And if we specify `DefaultButton` to be "two": + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, + DefaultButton: "two", +}) +``` + +the second button is shown as default. When `return` is pressed, the value "two" is returned. + +```mdx-code-block +
+ +
+
+``` + +If we now specify `CancelButton` to be "three": + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, + DefaultButton: "two", + CancelButton: "three", +}) +``` + +the button with "three" is shown at the bottom of the dialog. When `escape` is pressed, the value "three" is returned: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### DialogType + +```go +const ( + InfoDialog DialogType = "info" + WarningDialog DialogType = "warning" + ErrorDialog DialogType = "error" + QuestionDialog DialogType = "question" + ) +``` + +### FileFilter + +```go +type FileFilter struct { + DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)" + Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png" +} +``` + +#### Windows + +Windows allows you to use multiple file filters in dialog boxes. Each FileFilter will show up as a separate entry in the dialog: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### Linux + +Linux allows you to use multiple file filters in dialog boxes. Each FileFilter will show up as a separate entry in the dialog: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### Mac + +Mac dialogs only have the concept of a single set of patterns to filter files. If multiple FileFilters are provided, Wails will use all the Patterns defined. + +Example: + +```go + selection, err := runtime.OpenFileDialog(b.ctx, runtime.OpenDialogOptions{ + Title: "Select File", + Filters: []runtime.FileFilter{ + { + DisplayName: "Images (*.png;*.jpg)", + Pattern: "*.png;*.jpg", + }, { + DisplayName: "Videos (*.mov;*.mp4)", + Pattern: "*.mov;*.mp4", + }, + }, + }) +``` + +This will result in the Open File dialog using `*.png,*.jpg,*.mov,*.mp4` as a filter. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx new file mode 100644 index 00000000000..856ba6f0c26 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx @@ -0,0 +1,37 @@ +--- +sidebar_position: 2 +--- + +# Events + +The Wails runtime provides a unified events system, where events can be emitted or received by either Go or JavaScript. Optionally, data may be passed with the events. Listeners will receive the data in the local data types. + +### EventsOn + +This method sets up a listener for the given event name. When an event of type `eventName` is [emitted](#EventsEmit), the callback is triggered. Any additional data sent with the emitted event will be passed to the callback. It returns a function to cancel the listener. + +Go: `EventsOn(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`
JS: `EventsOn(eventName string, callback function(optionalData?: any)): () => void` + +### EventsOff + +This method unregisters the listener for the given event name, optionally multiple listeneres can be unregistered via `additionalEventNames`. + +Go: `EventsOff(ctx context.Context, eventName string, additionalEventNames ...string)`
JS: `EventsOff(eventName string, ...additionalEventNames)` + +### EventsOnce + +This method sets up a listener for the given event name, but will only trigger once. It returns a function to cancel the listener. + +Go: `EventsOnce(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`
JS: `EventsOnce(eventName string, callback function(optionalData?: any)): () => void` + +### EventsOnMultiple + +This method sets up a listener for the given event name, but will only trigger a maximum of `counter` times. It returns a function to cancel the listener. + +Go: `EventsOnMultiple(ctx context.Context, eventName string, callback func(optionalData ...interface{}), counter int) func()`
JS: `EventsOnMultiple(eventName string, callback function(optionalData?: any), counter int): () => void` + +### EventsEmit + +This method emits the given event. Optional data may be passed with the event. This will trigger any event listeners. + +Go: `EventsEmit(ctx context.Context, eventName string, optionalData ...interface{})`
JS: `EventsEmit(eventName: string, ...optionalData: any)` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx new file mode 100644 index 00000000000..3cacb6ba9a7 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx @@ -0,0 +1,85 @@ +--- +sidebar_position: 1 +--- + +# 소개 + +런타임은 애플리케이션에 유틸리티 메서드를 제공하는 라이브러리입니다. There is both a Go and JavaScript runtime and the aim is to try and keep them at parity where possible. + +다음에 대한 유틸리티 메서드가 있습니다: + +- [Window](window.mdx) +- [Menu](menu.mdx) +- [Dialog](dialog.mdx) +- [Events](events.mdx) +- [Browser](browser.mdx) +- [Log](log.mdx) +- [Clipboard](clipboard.mdx) + +Go 런타임은 `github.com/wailsapp/wails/v2/pkg/runtime` 가져오기를 통해 사용할 수 있습니다. 이 패키지의 모든 메소드는 컨텍스트를 첫 번째 매개변수로 사용합니다. 이 컨텍스트는 [OnStartup](../options.mdx#onstartup) 또는 [OnDomReady](../options.mdx#ondomready) 후크에서 가져와야 합니다. + +:::참고 + +컨텍스트는 [OnStartup](../options.mdx#onstartup) 메서드를 사용할 경우 런타임이 이 메서드에서 다음과 같이 작동할 것이라는 보장은 없습니다. 창이 다른 스레드에서 초기화되고 있습니다. 시작 시 런타임 메서드를 호출하려면 [OnDomReady](../options.mdx#ondomready)를 사용하세요. + +::: + +The JavaScript library is available to the frontend via the `window.runtime` map. There is a runtime package generated when using `dev` mode that provides TypeScript declarations for the runtime. 이것은 프론트엔드 디렉토리의 `wailsjs` 디렉토리에 있어야 합니다. + +### Hide + +Go: `Hide(ctx context.Context)`
JS: `Hide()` + +애플리케이션을 숨깁니다. + +:::참고 + +On Mac, this will hide the application in the same way as the `Hide` menu item in standard Mac applications. This is different to hiding the window, but the application still being in the foreground. For Windows and Linux, this is currently the same as `WindowHide`. + +::: + +### Show + +Shows the application. + +:::참고 + +On Mac, this will bring the application back into the foreground. For Windows and Linux, this is currently the same as `WindowShow`. + +::: + +Go: `Show(ctx context.Context)`
JS: `Show()` + +### Quit + +Quits the application. + +Go: `Quit(ctx context.Context)`
JS: `Quit()` + +### Environment + +Returns details of the current environment. + +Go: `Environment(ctx context.Context) EnvironmentInfo`
JS: `Environment(): Promise` + +#### EnvironmentInfo + +Go: + +```go +type EnvironmentInfo struct { + BuildType string + Platform string + Arch string +} +``` + +JS: + +```ts +interface EnvironmentInfo { + buildType: string; + platform: string; + arch: string; +} +``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx new file mode 100644 index 00000000000..2112e1c9e4f --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 3 +--- + +# Log + +The Wails runtime provides a logging mechanism that may be called from Go or JavaScript. 대부분처럼 loggers 에는 다양한 로그 수준이 있습니다: + +- Trace +- Debug +- Info +- Warning +- Error +- Fatal + +Logger는 현재 이상의 로그 수준에서 모든 로그 메시지를 출력합니다. Example: `Debug` 로그 level은 `Trace` 메시지를 제외한 모든 메시지를 출력합니다. + +### LogPrint + +주어진 메시지를 원본 메시지로 기록합니다. + +Go: `LogPrint(ctx context.Context, message string)`
JS: `LogPrint(message: string)` + +### LogPrintf + +주어진 메시지를 원본 메시지로 기록합니다. + +Go: `LogPrintf(ctx context.Context, format string, args ...interface{})`
+ +### LogTrace + +`Trace` 로그 수준에서 지정된 메시지를 기록합니다. + +Go: `LogTrace(ctx context.Context, message string)`
JS: `LogTrace(message: string)` + +### LogTracef + +`Trace` 로그 수준에서 지정된 메시지를 기록합니다. + +Go: `LogTracef(ctx context.Context, format string, args ...interface{})`
+ +### LogDebug + +`Debug` 로그 수준에서 지정된 메시지를 기록합니다. + +Go: `LogDebug(ctx context.Context, message string)`
JS: `LogDebug(message: string)` + +### LogDebugf + +`Debug` 로그 수준에서 지정된 메시지를 기록합니다. + +Go: `LogDebugf(ctx context.Context, format string, args ...interface{})`
+ +### LogInfo + +`Info` 로그 수준에서 지정된 메시지를 기록합니다. + +Go: `LogInfo(ctx context.Context, message string)`
JS: `LogInfo(message: string)` + +### LogInfof + +`Info` 로그 수준에서 지정된 메시지를 기록합니다. + +Go: `LogInfof(ctx context.Context, format string, args ...interface{})`
+ +### LogWarning + +`Warning` 로그 수준에서 지정된 메시지를 기록합니다. + +Go: `LogWarning(ctx context.Context, message string)`
JS: `LogWarning(message: string)` + +### LogWarningf + +`Warning` 로그 수준에서 지정된 메시지를 기록합니다. + +Go: `LogWarningf(ctx context.Context, format string, args ...interface{})`
+ +### LogError + +`Error` 로그 수준에서 지정된 메시지를 기록합니다. + +Go: `LogError(ctx context.Context, message string)`
JS: `LogError(message: string)` + +### LogErrorf + +`Error` 로그 수준에서 지정된 메시지를 기록합니다. + +Go: `LogErrorf(ctx context.Context, format string, args ...interface{})`
+ +### LogFatal + +`Fatal` 로그 수준에서 지정된 메시지를 기록합니다. + +Go: `LogFatal(ctx context.Context, message string)`
JS: `LogFatal(message: string)` + +### LogFatalf + +`Fatal` 로그 수준에서 지정된 메시지를 기록합니다. + +Go: `LogFatalf(ctx context.Context, format string, args ...interface{})`
+ +### LogSetLogLevel + +로그 레벨을 설정합니다. In JavaScript, the number relates to the following log levels: + +| 값 | 로그 레벨 | +| - | ------- | +| 1 | Trace | +| 2 | Debug | +| 3 | Info | +| 4 | Warning | +| 5 | Error | + +Go: `LogSetLogLevel(ctx context.Context, level logger.LogLevel)`
JS: `LogSetLogLevel(level: number)` + +## 커스텀 Logger 사용하기 + +사용자 커스텀 logger는 [Logger](../options.mdx#logger)를 사용하여 제공하여 사용할 수 있습니다. 응용 프로그램 옵션. 유일한 요구 사항은 logger가 `logger.Logger` 인터페이스를 구현한다는 것입니다. 이는 `github.com/wailsapp/wails/v2/pkg/logger`에 정의되어 있습니다: + +```go title="logger.go" +type Logger interface { + Print(message string) + Trace(message string) + Debug(message string) + Info(message string) + Warning(message string) + Error(message string) + Fatal(message string) +} +``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx new file mode 100644 index 00000000000..0eab71c0162 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx @@ -0,0 +1,25 @@ +--- +sidebar_position: 6 +--- + +# 메뉴 + +애플리케이션 메뉴는 이 메소드들과 관련 있습니다. + +:::info JavaScript + +현재 메뉴는 JS runtime을 지원하지 않습니다. + +::: + +### MenuSetApplicationMenu + +애플리케이션 메뉴는 [menu](../menus.mdx)를 통해 설정하세요. + +Go: `MenuSetApplicationMenu(ctx context.Context, menu *menu.Menu)` + +### MenuUpdateApplicationMenu + +애플리케이션 메뉴를 업데이트하여 `MenuSetApplicationMenu`에 전달된 메뉴에 대한 모든 변경 사항을 선택합니다. + +Go: `MenuUpdateApplicationMenu(ctx context.Context)` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx new file mode 100644 index 00000000000..457c92ebff9 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx @@ -0,0 +1,38 @@ +--- +sidebar_position: 9 +--- + +# Screen + +These methods provide information about the currently connected screens. + +### ScreenGetAll + +Returns a list of currently connected screens. + +Go: `ScreenGetAll(ctx context.Context) []screen`
+JS: `ScreenGetAll()` + +#### Screen + +Go struct: + +```go +type Screen struct { + IsCurrent bool + IsPrimary bool + Width int + Height int +} +``` + +Typescript interface: + +```ts +interface Screen { + isCurrent: boolean; + isPrimary: boolean; + width : number + height : number +} +``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx new file mode 100644 index 00000000000..8e1052289b9 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx @@ -0,0 +1,227 @@ +--- +sidebar_position: 4 +--- + +# Window + +이러한 메서드는 응용 프로그램 창을 제어합니다. + +### WindowSetTitle + +창 제목 표시줄의 텍스트를 설정합니다. + +Go: `WindowSetTitle(ctx context.Context, title string)`
JS: `WindowSetTitle(title: string)` + +### WindowFullscreen + +창을 전체화면으로 만듭니다. + +Go: `WindowFullscreen(ctx context.Context)`
JS: `WindowFullscreen()` + +### WindowUnfullscreen + +전체 화면 이전의 이전 창 크기와 위치를 복원합니다. + +Go: `WindowUnfullscreen(ctx context.Context)`
JS: `WindowUnfullscreen()` + +### WindowIsFullscreen + +창이 전체 화면이면 true를 반환합니다. + +Go: `WindowIsFullscreen(ctx context.Context) bool`
JS: `WindowIsFullscreen() bool` + +### WindowCenter + +창이 현재 켜져 있는 모니터의 중앙에 창을 맞춥니다. + +Go: `WindowCenter(ctx context.Context)`
JS: `WindowCenter()` + +### WindowExecJS + +창에서 임의의 JS 코드를 실행합니다. + +이 메서드는 브라우저에서 코드를 비동기적으로 실행하고 즉시 반환합니다. 만약 스크립트에서 오류가 발생하면 브라우저 콘솔에서만 사용할 수 있습니다. + +Go: `WindowExecJS(ctx context.Context, js string)` + +### WindowReload + +"새로고침"을 수행합니다(현재 페이지 새로고침). + +Go: `WindowReload(ctx context.Context)`
JS: `WindowReload()` + +### WindowReloadApp + +프론트엔드 애플리케이션을 새로고침합니다. + +Go: `WindowReloadApp(ctx context.Context)`
JS: `WindowReloadApp()` + +### WindowSetSystemDefaultTheme + +윈도우 전용. + +Go: `WindowSetSystemDefaultTheme(ctx context.Context)`
JS: `WindowSetSystemDefaultTheme()` + +창의 테마를 시스템 기본값으로 설정합니다(다크/라이트). + +### WindowSetLightTheme + +윈도우 전용. + +Go: `WindowSetLightTheme(ctx context.Context)`
JS: `WindowSetLightTheme()` + +창 테마를 라이트 모드로 설정합니다. + +### WindowSetDarkTheme + +윈도우 전용. + +Go: `WindowSetDarkTheme(ctx context.Context)`
JS: `WindowSetDarkTheme()` + +윈도우 테마를 다크로 설정합니다. + +### WindowShow + +만약 현재 창의 상태가 숨기기로 되어 있다면, 창을 보여줍니다. + +Go: `WindowShow(ctx context.Context)`
JS: `WindowShow()` + +### WindowHide + +현재 창이 표시되어 있는 경우 창을 숨깁니다. + +Go: `WindowHide(ctx context.Context)`
JS: `WindowHide()` + +### WindowIsNormal + +창이 최소화, 최대화 또는 전체 화면이 아닌 경우 true를 반환합니다. + +Go: `WindowIsNormal(ctx context.Context) bool`
JS: `WindowIsNormal() bool` + +### WindowSetSize + +창의 너비와 높이를 설정합니다. + +Go: `WindowSetSize(ctx context.Context, width int, height int)`
JS: `WindowSetSize(width: number, height: number)` + +### WindowGetSize + +창의 너비와 높이를 가져옵니다. + +Go: `WindowGetSize(ctx context.Context) (width int, height int)`
JS: `WindowGetSize() : Size` + +### WindowSetMinSize + +최소 창 크기를 설정합니다. 창이 현재 지정된 크기보다 작은 경우 창 크기를 조정합니다. + +`0,0`의 크기를 설정하면 이 제약 조건이 비활성화됩니다. + +Go: `WindowSetMinSize(ctx context.Context, width int, height int)`
JS: `WindowSetMinSize(width: number, height: number)` + +### WindowSetMaxSize + +최대 창 크기를 설정합니다. 창이 현재 지정된 크기보다 큰 경우 창 크기를 조정합니다. + +`0,0`의 크기를 설정하면 이 제약 조건이 비활성화됩니다. + +Go: `WindowSetMaxSize(ctx context.Context, width int, height int)`
JS: `WindowSetMaxSize(width: number, height: number)` + +### WindowSetAlwaysOnTop + +창을 항상위 또는 맨 위에 놓지 않도록 설정합니다. + +Go: `WindowSetAlwaysOnTop(ctx context.Context, b bool)`
JS: `WindowSetAlwaysOnTop(b: Boolen)` + +### WindowSetPosition + +창이 현재 켜져 있는 모니터를 기준으로 창 위치를 설정합니다. + +Go: `WindowSetPosition(ctx context.Context, x int, y int)`
JS: `WindowSetPosition(x: number, y: number)` + +### WindowGetPosition + +창이 현재 있는 모니터에 상대적인 창 위치를 가져옵니다. + +Go: `WindowGetPosition(ctx context.Context) (x int, y int)`
JS: `WindowGetPosition() : Position` + +### WindowMaximise + +창을 최대화하여 화면을 채웁니다. + +Go: `WindowMaximise(ctx context.Context)`
JS: `WindowMaximise()` + +### WindowUnmaximise + +창을 최대화하기 전의 크기와 위치로 복원합니다. + +Go: `WindowUnmaximise(ctx context.Context)`
JS: `WindowUnmaximise()` + +### WindowIsMaximised + +창이 최대화되면 true를 반환합니다. + +Go: `WindowIsMaximised(ctx context.Context) bool`
JS: `WindowIsMaximised() bool` + +### WindowToggleMaximise + +최대화와 최대화 해제 사이를 전환합니다. + +Go: `WindowToggleMaximise(ctx context.Context)`
JS: `WindowToggleMaximise()` + +### WindowMinimise + +창을 최소화합니다. + +Go: `WindowMinimise(ctx context.Context)`
JS: `WindowMinimise()` + +### WindowUnminimise + +최소화하기 전의 크기와 위치로 창을 복원합니다. + +Go: `WindowUnminimise(ctx context.Context)`
JS: `WindowUnminimise()` + +### WindowIsMinimised + +창이 최소화된 경우 true를 반환합니다. + +Go: `WindowIsMinimised(ctx context.Context) bool`
JS: `WindowIsMinimised() bool` + +### WindowSetBackgroundColour + +창의 배경색을 지정된 RGBA 색상 정의로 설정합니다. 이 색상은 모든 투명 픽셀에 대해 표시됩니다. + +R, G, B 및 A의 유효한 값은 0-255입니다. + +:::info Windows + +Windows에서는 0 또는 255의 알파 값만 지원됩니다. 0이 아닌 모든 값은 255로 간주됩니다. + +::: + +Go: `WindowSetBackgroundColour(ctx context.Context, R, G, B, A uint8)`
JS: `WindowSetBackgroundColour(R, G, B, A)` + +### WindowPrint + +Opens tha native print dialog. + +Go: `WindowPrint(ctx context.Context)`
JS: `WindowPrint()` + +## TypeScript Object Definitions + +### 위치 + +```ts +interface Position { + x: number; + y: number; +} +``` + +### 크기 + +```ts +interface Size { + w: number; + h: number; +} +``` diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx new file mode 100644 index 00000000000..98129e5b753 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx @@ -0,0 +1,245 @@ +--- +sidebar_position: 20 +--- + +# Dogs API + +```mdx-code-block +
+ +
+
+``` + +:::note + +이 튜토리얼은 [@tatadan](https://twitter.com/tatadan)에 의해 제공되었습니다. 그리고 [ Wails 예시 리포지토리](https://github.com/tataDan/wails-v2-examples)에서 예시를 확인할 수 있습니다. + +::: + +이 튜토리얼에서는 웹에서 개 사진을 검색한 다음 표시하는 애플리케이션을 개발할 것입니다. + +### 프로젝트 생성 + +애플리케이션을 생성합니다. 터미널에 다음과 같이 입력합니다: `wails init -n dogs-api -t svelte` + +참고: 원하는 경우 선택적으로 이 명령의 끝에 `-ide vscode` 또는 `-ide goland`를 추가할 수 있습니다. IDE 지원을 추가합니다. + +이제 `cd dogs-api`를 만들고 프로젝트 파일 편집을 시작합니다. + +### 사용하지 않는 코드 제거 + +사용하지 않는 몇가지 요소를 제거합니다. + +- `app.go`를 열고 다음 줄을 제거합니다. + +```go +// Greet returns a greeting for the given name +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s, It's show time!", name) +} +``` + +- `frontend/src/App.svelte`를 열고 모든 줄을 삭제합니다. +- `frontend/src/assets/images/logo-universal.png` 파일을 삭제합니다. + +### 우리만의 애플리케이션 생성하기 + +이제 새로운 Go 코드를 추가합니다. + +함수 정의 앞에 다음 구조체 선언을 `app.go`에 추가합니다. + +```go +type RandomImage struct { + Message string + Status string +} + +type AllBreeds struct { + Message map[string]map[string][]string + Status string +} + +type ImagesByBreed struct { + Message []string + Status string +} +``` + +`app.go`에 다음 함수를 추가합니다(함수 정의 뒤쪽에 존재): + +```go +func (a *App) GetRandomImageUrl() string { + response, err := http.Get("https://dog.ceo/api/breeds/image/random") + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data RandomImage + json.Unmarshal(responseData, &data) + + return data.Message +} + +func (a *App) GetBreedList() []string { + var breeds []string + + response, err := http.Get("https://dog.ceo/api/breeds/list/all") + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data AllBreeds + json.Unmarshal(responseData, &data) + + for k := range data.Message { + breeds = append(breeds, k) + } + + sort.Strings(breeds) + + return breeds +} + +func (a *App) GetImageUrlsByBreed(breed string) []string { + + url := fmt.Sprintf("%s%s%s%s", "https://dog.ceo/api/", "breed/", breed, "/images") + response, err := http.Get(url) + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data ImagesByBreed + json.Unmarshal(responseData, &data) + + return data.Message +} +``` + +`app.go`의 `import` 섹션을 다음과 같이 수정합니다. + +```go +import ( + "context" + "fmt" + "encoding/json" + "io/ioutil" + "log" + "net/http" + "sort" +) +``` + +`frontend/src/App.svelte`에 다음 줄을 추가합니다. + + +```html + + +

Dogs API

+
+ + Click on down arrow to select a breed + + +
+
+{#if showRandomPhoto} + No dog found +{/if} +{#if showBreedPhotos} + {#each photos as photo} + No dog found + {/each} +{/if} + + +``` + + +### 애플리케이션 테스트하기 + +바인딩을 생성하고 애플리케이션을 테스트하려면 `wails dev`를 실행합니다. + +### 애플리케이션 컴파일하기 + +응용 프로그램을 단일 바이너리로 컴파일하려면 `wails build`를 실행합니다. diff --git a/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx new file mode 100644 index 00000000000..4bc3bcaafc2 --- /dev/null +++ b/website/i18n/ko/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx @@ -0,0 +1,123 @@ +--- +sidebar_position: 10 +--- + +# Hello World + +이 튜토리얼의 목표는 Wails를 사용하여 가장 기본적인 애플리케이션을 시작하고 실행하는 것입니다. 튜토리얼을 통해 다음과 같은 것들을 할 수있습니다. + +- 새로운 Wails 애플리케이션 생성 +- 애플리케이션 빌드 +- 애플리케이션 실행 + +:::note + +이 튜토리얼에서는 Windows를 대상 플랫폼으로 사용합니다. 출력이 약간 다를 수 있습니다. 운영체제에 따라 다릅니다. + +::: + +## 새로운 Wails 애플리케이션 생성 + +기본 바닐라 JS 템플릿을 사용하여 새 Wails 애플리케이션을 만들려면, 다음 명령을 실행해야 합니다: + +```bash +wails init -n helloworld +``` + +실행 결과로 다음과 유사한 결과가 반환됩니다. + +``` +Wails CLI v2.0.0 + +Initialising Project 'helloworld' +--------------------------------- + +Project Name: helloworld +Project Directory: C:\Users\leaan\tutorial\helloworld +Project Template: vanilla +Template Support: https://wails.io + +Initialised project 'helloworld' in 232ms. +``` + +이렇게 하면 현재 디렉터리에 `helloworld`라는 새 디렉터리가 생성됩니다. 이 디렉토리에는 여러 파일이 있습니다: + +``` +build/ - Contains the build files + compiled application +frontend/ - Contains the frontend files +app.go - Contains the application code +main.go - The main program with the application configuration +wails.json - The project configuration file +go.mod - The go module file +go.sum - The go module checksum file +``` + +## 애플리케이션 빌드 + +애플리케이션을 빌드하려면 새 `helloworld` 프로젝트 디렉토리로 변경하고 다음 명령을 실행하십시오. + +```bash +wails build +``` + +다음과 같은 내용이 표시되어야 합니다: + +``` +Wails CLI v2.0.0 + +App Type: desktop +Platforms: windows/amd64 +Compiler: C:\Users\leaan\go\go1.18.3\bin\go.exe +Build Mode: Production +Devtools: false +Skip Frontend: false +Compress: false +Package: true +Clean Build Dir: false +LDFlags: "" +Tags: [] +Race Detector: false + +Building target: windows/amd64 +------------------------------ + - Installing frontend dependencies: Done. + - Compiling frontend: Done. + - Generating bundle assets: Done. + - Compiling application: Done. +Built 'C:\Users\leaan\tutorial\helloworld\build\bin\helloworld.exe' in 10.616s. +``` + +이것은 애플리케이션을 컴파일하고 `build/bin` 디렉토리에 결과 실행파일을 저장합니다. + +## 애플리케이션 실행 + +Windows 탐색기에서 `build/bin` 디렉토리를 보면 프로젝트 바이너리가 표시되어야 합니다. + +```mdx-code-block +
+ +
+
+``` + +`helloworld.exe` 파일을 두 번 클릭하면 실행됩니다. + +Mac에서 Wails는 두 번 클릭하여 실행할 수 있는 `helloworld.app` 파일을 생성합니다. + +Linux에서는 `build/bin` 디렉토리에서 `./helloworld`를 사용하여 애플리케이션을 실행할 수 있습니다. + +애플리케이션이 예상대로 동작하는지 확인해야 합니다. + +```mdx-code-block +
+ +
+
+``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx new file mode 100644 index 00000000000..006ff61ed06 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 2 +--- + +# Links + +Esta página serve como uma lista para links da comunidade relacionados. Envie um PR (clique `Editar esta página` na parte inferior) para enviar links. + +## Awesome Wails + +A [lista definitiva](https://github.com/wailsapp/awesome-wails) dos links relacionados à Wails. + +## Canais de Suporte + +- [Servidor do Discord Wails](https://discord.gg/JDdSxwjhGf) +- [Github Issues](https://github.com/wailsapp/wails/issues) +- [v2 Beta Discussion Board](https://github.com/wailsapp/wails/discussions/828) + +## Redes Sociais + +- [Twitter](https://twitter.com/wailsapp) +- [Wails Chinese Community QQ Group](https://qm.qq.com/cgi-bin/qm/qr?k=PmIURne5hFGNd7QWzW5qd6FV-INEjNJv&jump_from=webapi) - Group number: 1067173054 + +## Outros tutoriais e Artigos + +- [Building of Bulletin Board](https://blog.customct.com/building-bulletin-board) diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx new file mode 100644 index 00000000000..6373a7ff16e --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx @@ -0,0 +1,10 @@ +# BulletinBoard + +```mdx-code-block +

+ +
+

+``` + +O aplicativo [BulletinBoard](https://github.com/raguay/BulletinBoard) é um quadro de mensagens versitais para mensagens estáticas ou diálogos para obter informações do usuário para um script. Ele tem uma TUI para criar novas caixas de diálogo que podem ser usadas por último para obter informações do usuário. É um design que fica em execução no seu sistema e mostra as informações conforme necessário e depois se esconde. Tenho um processo para assistir um arquivo no meu sistema e enviar o conteúdo para o BulletinBoard quando alterado. Funciona bem com meus fluxos de trabalho. Há também um [fluxo de trabalho Alfred](https://github.com/raguay/MyAlfred/blob/master/Alfred%205/EmailIt.alfredworkflow) para enviar informações ao programa. O fluxo de trabalho também é para trabalhar com [EmailIt](https://github.com/raguay/EmailIt). diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..642dd1ba1d5 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx @@ -0,0 +1,41 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Acompanhe +qualquer partida ao vivo do perfil Street Fighter 6 ou V CFN. Verifique +[o site](https://cfn.williamsjokvist.se/) para começar. + +## Características + +- Acompanhamento de partidas em tempo real +- Armazenamento de registros e estatísticas de partidas +- Suporte para exibição de estatísticas ao vivo no OBS via fonte do navegador +- Suporte para SF6 e SFV +- Capacidade para os usuários criarem seus próprios temas do navegador OBS com + CSS + +### Principais tecnologias usadas junto com Wails + +- [Tarefa](https://github.com/go-task/task) - agrupando a CLI do Wails para + facilitar o uso de comandos comuns +- [React](https://github.com/facebook/react) - escolhido por seu rico + ecossistema (radix, framer-motion) +- [Bun](https://github.com/oven-sh/bun) - usado por sua rápida resolução de + dependências e tempo de construção +- [Rod](https://github.com/go-rod/rod) - automação de navegador headless para + autenticação e alterações de pesquisa +- [SQLite](https://github.com/mattn/go-sqlite3) - usado para armazenar + correspondências, sessões e perfis +- [Eventos enviados pelo servidor](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + um fluxo http para enviar atualizações de rastreamento para fontes do + navegador OBS +- [i18next](https://github.com/i18next/) - com conector de back-end para servir + objetos de localização da camada Go +- [xstate](https://github.com/statelyai/xstate) - máquinas de estado para + processo de autenticação e rastreamento diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx new file mode 100644 index 00000000000..862c304e973 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx @@ -0,0 +1,10 @@ +# EmailIt + +```mdx-code-block +

+ +
+

+``` + +[EmailIt](https://github.com/raguay/EmailIt/) é um programa Wails 2 que é um remetente de e-mail baseado em markdown com apenas nove notepads, scripts para manipular o texto e templates. Ele também tem um terminal para rodar scripts em EmailIt em arquivos do seu sistema. Os scripts e modelos podem ser usados na própria linha de comando ou com as extensões Alfred, Keyboard Maestro, Dropzone ou PopClip. Ele também suporta scripts e temas baixados no formulário GitHub. A documentação não está completa, mas os programas funcionam. É construído usando Wails2 e Svelte, e o download é um aplicativo macOS universal. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx new file mode 100644 index 00000000000..a5692d35388 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx @@ -0,0 +1,12 @@ +# EncryptEasy + +```mdx-code-block +

+ +
+

+``` + +**[EncryptEasy](https://www.encrypteasy.app) é uma ferramenta simples e fácil de usar de criptografia PGP, gerenciando todas as suas chaves de contato e suas chaves. A criptografia deve ser simples. Desenvolvido com Wails.** + +Criptografar mensagens usando PGP é o padrão da indústria. Todos têm uma chave privada e pública. A sua chave privada precisa ser privada para que apenas você possa ler as mensagens. Sua chave pública é distribuída para qualquer pessoa que queira lhe enviar o segredo, mensagens criptografadas. Gerenciar chaves, criptografar mensagens e descriptografar mensagens devem ser uma experiência suave. EncryptEasy é sobre facilitar o processo. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx new file mode 100644 index 00000000000..78c79769f7e --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx @@ -0,0 +1,13 @@ +# ESP Studio + +```mdx-code-block +

+ +
+

+``` + +[ESP Studio](https://github.com/torabian/esp-studio) - Software multiplataforma, desktop, nuvem e incorporado +para controlar dispositivos ESP/Arduino e construir fluxos de trabalho e sistemas de controle IOT complexos \ No newline at end of file diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx new file mode 100644 index 00000000000..0b5d7fc36ba --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx @@ -0,0 +1,16 @@ +# Utilitário de Exportação FileHound + +```mdx-code-block +

+ +
+

+``` + +[Utilitário de exportação de FileHound](https://www.filehound.co.uk/) FileHound é uma plataforma de gerenciamento de documentos em nuvem feita para retenção segura de arquivos, automação de processos de negócio e recursos de SmartCaptura. + +O Utilitário de Exportação FileHound permite os admnistradores FileHound a capacidade de executar um documento seguro e extração de tarefas para um backup alternativo. Esta aplicação irá baixar todos os documentos e/ou meta dados salvos no FileHound com base nos filtros que você escolher. Os metadados serão exportados em ambos os formatos JSON e XML. + +Backend construído com: Go 1.15 Wails 1.11.0 go-sqlite3 1.14.6 go-linq 3.2 + +Frontend com: Vue 2.6.11 Vuex 3.4.0 TypeScript Tailwind 1.9.6 diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx new file mode 100644 index 00000000000..13ed9dc7c53 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx @@ -0,0 +1,10 @@ +# hiposter + +```mdx-code-block +

+ +
+

+``` + +[hiposter](https://github.com/obity/hiposter) é uma ferramenta simples e eficiente de teste de cliente http API. Baseado em Wails, Go and sveltejs. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx new file mode 100644 index 00000000000..d606f87f961 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx @@ -0,0 +1,14 @@ +# Atualizador do Minecraft + +```mdx-code-block +

+ +
+

+``` + +[O atualziador do Minecraft](https://github.com/Gurkengewuerz/MinecraftModUpdater) é uma ferramenta utilitária para atualizar e sincronizar mods do Minecraft para sua base de usuários. Ele é construído usando Wails2 e React com [antd](https://ant.design/) como framework frontend. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx new file mode 100644 index 00000000000..9633a7d4a84 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx @@ -0,0 +1,14 @@ +# Gerenciador de arquivos Modal + +```mdx-code-block +

+ +
+

+``` + +[Gerenciador de Arquivos Modal](https://github.com/raguay/ModalFileManager) é um gerenciador de arquivos dual pane usando tecnologias da web. Meu design original foi baseado em NW.js e pode ser encontrado [aqui](https://github.com/raguay/ModalFileManager-NWjs). Esta versão usa o mesmo código de frontend baseado em Svelte (mas foi muito modificado desde a partida do NW.), mas o backend implementado com [Wails 2](https://wails.io/). Ao usar esta implementação, não uso mais comandos de linha de comando `rm`, `cp`, etc., mas um git install deve estar no sistema para baixar temas e extensões. Está totalmente codificado usando Go e roda muito mais rápido do que as versões anteriores. + +Este gerenciador de arquivos é projetado em torno do mesmo princípio do Vim: uma ação controlada pelo teclado. O número de estados não é fixo, mas muito programável. Portanto, um número infinito de configurações de teclado pode ser criado e usado. Esta é a principal diferença em relação a outros gerenciadores de arquivos. Existem temas e extensões disponíveis para download do GitHub. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx new file mode 100644 index 00000000000..a0570d03546 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx @@ -0,0 +1,10 @@ +# Molley Wallet + +```mdx-code-block +

+ +
+

+``` + +[Molley Wallet](https://github.com/grvlle/constellation_wallet/) a carteira oficial $DAG da rede Constellation. Ele permitirá que os usuários interajam com a Rede Hypergraph de várias maneiras, não limitado à produção de $DAG transações. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx new file mode 100644 index 00000000000..0069bae7230 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx @@ -0,0 +1,14 @@ +# October + +```mdx-code-block +

+ +
+

+``` + +[Constellation ](https://october.utf9k.net) é uma pequena aplicação de Wails que facilita muito a extração de destaques de [Kobo eReaders](https://en.wikipedia.org/wiki/Kobo_eReader) e então os encaminha para [Readwise](https://readwise.io). + +Tem um escopo relativamente pequeno com todas as versões de plataforma pesando abaixo de 10MB, e isso é sem habilitar [a compressão UPX](https://upx.github.io/)! + +Em contraste, as tentativas anteriores do autor com o Electron rapidamente incharam várias centenas de megabytes. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx new file mode 100644 index 00000000000..606d5c4a87f --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx @@ -0,0 +1,10 @@ +# Optimus + +```mdx-code-block +

+ +
+

+``` + +[Optimus](https://github.com/splode/optimus) é uma aplicação de otimização de imagem para área de trabalho. Ele suporta conversão e compressão entre formatos de imagem WebP, JPEG e PNG. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx new file mode 100644 index 00000000000..4db08021efe --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx @@ -0,0 +1,10 @@ +# Portfall + +```mdx-code-block +

+ +
+

+``` + +[Portfall](https://github.com/rekon-oss/portfall) - Um portal de encaminhamento de porta para desktop para fácil acesso a todas as suas interfaces diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx new file mode 100644 index 00000000000..fbe86fd6db5 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx @@ -0,0 +1,12 @@ +# Restic Browser + +```mdx-code-block +

+ +
+

+``` + +[Restic-Browser](https://github.com/emuell/restic-browser) - Uma GUI de backup simples e multiplataforma [restica](https://github.com/restic/restic) para navegação e restauração de repositórios resóticos. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx new file mode 100644 index 00000000000..961debade5f --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx @@ -0,0 +1,21 @@ +# RiftShare + +```mdx-code-block +

+ +
+

+``` + +Compartilhamento de arquivos fácil, seguro e gratuito para todos. Saiba mais em [Riftshare.app](https://riftshare.app) + +## Funcionalidades + +- Compartilhamento fácil e seguro de arquivos entre computadores tanto na rede local quanto através da internet +- Suporta o envio de arquivos ou diretórios de forma segura através do [magic wormhole protocol](https://magic-wormhole.readthedocs.io/en/latest/) +- Compatível com todos os outros aplicativos que usam magic wormhole (magic-wormhole ou wormhole-william CLI, wormhole-gui, etc.) +- Compactação automática de vários arquivos selecionados para enviar de uma vez +- Animações completas, barra de progresso e cancelamento do suporte para envio e recebimento +- Seleção de arquivo Native OS +- Abrir arquivos em um clique uma vez recebido +- Atualização Automática - não se preocupe em ter a versão mais recente! diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx new file mode 100644 index 00000000000..335e360e37a --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx @@ -0,0 +1,10 @@ +# ScriptBar + +```mdx-code-block +

+ +
+

+``` + +[ScriptBar](https://GitHub.com/raguay/ScriptBarApp) é um programa que mostra a saída dos scripts ou o servidor [Node-Red](https://nodered.org). Ele executa scripts definidos no programa EmailIt e mostra a saída. Scripts de xBar ou TextBar podem ser usados, mas atualmente em scripts da TextBar funcionam bem. Também exibe a saída de scripts no seu sistema. ScriptBar não os coloca na barra de menus, mas os tenha todos em uma janela convidada para fácil visualização. Você pode ter várias abas para ter muitas coisas diferentes mostradas. Você também pode manter os links para os sites mais visitados. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx new file mode 100644 index 00000000000..78db0e7b460 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx @@ -0,0 +1,10 @@ +# Surge + +```mdx-code-block +

+ +
+

+``` + +[Surge](https://getsurge.io/) é um aplicativo de compartilhamento de arquivos p2p projetado para utilizar tecnologias blockchain para habilitar transferências de arquivos 100% anônimas. O Surgeé criptografado, descentralizado e de código aberto. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx new file mode 100644 index 00000000000..e3124bab727 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx @@ -0,0 +1,11 @@ +# Tiny RDM + +```mdx-code-block +

+ + +
+

+``` + +The [Tiny RDM](https://redis.tinycraft.cc/) application is an open-source, modern lightweight Redis GUI. It has a beautful UI, intuitive Redis database management, and compatible with Windows, Mac, and Linux. It provides visual key-value data operations, supports various data decoding and viewing options, built-in console for executing commands, slow log queries and more. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx new file mode 100644 index 00000000000..8b2f2c6c4fb --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx @@ -0,0 +1,10 @@ +# Wally + +```mdx-code-block +

+ +
+

+``` + +[Wally](https://ergodox-ez.com/pages/wally) é o flasher oficial para os teclados [Ergodox](https://ergodox-ez.com/). Parece excelente e é um exemplo fantástico do que você pode conseguir com o Wails: a capacidade de combinar o poder do Go e as ricas ferramentas gráficas do mundo de desenvolvimento web. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx new file mode 100644 index 00000000000..c56880f0e19 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx @@ -0,0 +1,19 @@ +# Launcher Minecraft para WarMine + +```mdx-code-block +

+ + +
+

+``` + +[Minecraft Launcher para WarMine](https://warmine.ru/) é uma aplicação Wails que permite que você entre nos servidores de jogos modificados facilmente e gerencie suas contas de jogo. + +O Launcher baixa os arquivos do jogo, verifica sua integridade e lança o jogo com uma grande variedade de opções de personalização para os argumentos de lançamento pelo backend. + +Frontend está escrito em Svelte, todo o launcher se enquadra em 9MB e suporta Windows 7-11. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx new file mode 100644 index 00000000000..d2e5eaf3ee6 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx @@ -0,0 +1,10 @@ +# Wombat + +```mdx-code-block +

+ +
+

+``` + +[Wombat](https://github.com/rogchap/wombat) é um cliente gRPC multiplataforma. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx new file mode 100644 index 00000000000..01a56449817 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx @@ -0,0 +1,10 @@ +# Ytd + +```mdx-code-block +

+ +
+

+``` + +[Ytd](https://github.com/marcio199226/ytd/tree/v2-wails) é um aplicativo para baixar faixas do youtube, criar listas de reprodução offline e compartilhar com seus amigos, seus amigos poderão reproduzir suas playlists ou baixá-las para escuta offline, tem um player embutido. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx new file mode 100644 index 00000000000..5fab64fd42a --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx @@ -0,0 +1,69 @@ +--- +sidebar_position: 1 +--- + +# Templates + +Esta página serve como uma lista para modelos suportados pela comunidade. Por favor, envie um PR (clique `Editar esta página` na parte inferior) para incluir seus modelos. Para construir seu próprio modelo, consulte o guia de [Modelos](../guides/templates.mdx). + +Para usar estes templates, execute `wails init -n "Seu Nome do Projeto" -t [o link abaixo[@version]]` + +Se não houver nenhum sufixo de versão, o modelo de código principal da branch é usado por padrão. Se houver um sufixo de versão, o template de código correspondente à tag desta versão é usado. + +Exemplo: `wails init -n "Seu Nome do Projeto" -t https://github.com/misitebao/wails-template-vue` + +:::warning Atenção + +**O projeto Wails não é mantido, não é responsável nem responsável por modelos de terceiros!** + +Se você não tiver certeza sobre um template, inspecione `package.json` e `wails.json` para quais scripts são executados e quais pacotes estão instalados. + +::: + +## Vue + +- [wails-template-vue](https://github.com/misitebao/wails-template-vue) - Wails template based on Vue ecology (Integrated TypeScript, Dark theme, Internationalization, Single page routing, TailwindCSS) +- [wails-vite-vue-ts](https://github.com/codydbentley/wails-vite-vue-ts) - Vue 3 TypeScript with Vite (and instructions to add features) +- [wails-vite-vue-the-works](https://github.com/codydbentley/wails-vite-vue-the-works) - Vue 3 TypeScript with Vite, Vuex, Vue Router, Sass, and ESLint + Prettier +- [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - Um template usando JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier) +- [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - Um modelo usando TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier, API de composição com <configuração de script>) +- [wails-template-naive](https://github.com/tk103331/wails-template-naive) - Modelo de ervas baseado em Naive UI (biblioteca de componentes Vue 3) + +## Angular + +- [A-modelo de wails-angular](https://github.com/mateothegreat/wails-template-angular) - ação Angular 15 + compactada & pronta para ser rolada para produção. +- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - Angular with TypeScript, Sass, Hot-Reload, Code-Splitting and i18n + +## React + +- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - A template using reactjs +- [wails-react-template](https://github.com/flin7/wails-react-template) - A minimal template for React that supports live development +- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - A template using Next.js and TypeScript +- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - A template for React + TypeScript + Vite + TailwindCSS +- [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - Um modelo com Vite, React, TypeScript, TailwindCSS, e shadcn/ui + +## Svelte + +- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - A template using Svelte +- [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - A template using Svelte and Vite +- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - A template using Svelte and Vite with TailwindCSS v3 +- [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - Um modelo atualizado usando Svelte v4.2.0 e Vite com TailwindCSS v3.3.3 +- [wails-sveltekit-template](https://github.com/h8gi/wails-sveltekit-template) - A template using SvelteKit + +## Solid + +- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-ts) - Um modelo usando Sólido + Ts + Vite +- [wails-template-vite-solid-js](https://github.com/xijaja/wails-template-solid-js) - Um modelo usando Sólid + Js + Vite + +## Elm + +- [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - Develop your GUI app with functional programming and a **snappy** hot-reload setup :tada: :rocket: +- [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - Combine the powers :muscle: of Elm + Tailwind CSS + Wails! Hot reloading supported. + +## HTMX + +- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - Use a unique combination of pure htmx for interactivity plus templ for creating components and forms + +## Pure JavaScript (Vanilla) + +- [wails-pure-js-template](https://github.com/KiddoV/wails-pure-js-template) - A template with nothing but just basic JavaScript, HTML, and CSS diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx new file mode 100644 index 00000000000..d06faa9eab2 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx @@ -0,0 +1,22 @@ +--- +sidebar_position: 6 +--- + +# Compilando seu projeto + +No diretório do projeto, execute `wails builds`. Isso compilará seu projeto e salvará o binário pronto para produção no diretório `build/bin`. + +Se você executar o binário, você verá a aplicação padrão: + +```mdx-code-block +
+ +
+
+``` + +Para mais detalhes sobre as opções de compilação, consulte a [Referência do CLI](../reference/cli.mdx#build). diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx new file mode 100644 index 00000000000..be641d3b98d --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx @@ -0,0 +1,16 @@ +--- +sidebar_position: 5 +--- + +# Desenvolvendo sua aplicação + +Você pode executar sua aplicação no modo de desenvolvimento executando `wails dev` no diretório do seu projeto. Isso fará o seguinte: + +- Construa seu aplicativo e o execute +- Vincule seu código Go para o frontend para que ele possa ser chamado a partir de JavaScript +- Usando o poder do [Vite](https://vitejs.dev/), observará modificações em seus arquivos Go e reconstruir/re-executar na alteração +- Configure um [servidor web](http://localhost:34115) que irá servir seu aplicativo em um navegador. Isso permite usar suas extensões de navegador favoritas. Você pode até mesmo chamar seu código Go do console + +Para começar, execute `wails dev` no diretório do projeto. Mais informações sobre isso podem ser encontradas [aqui](../reference/cli.mdx#dev). + +Em breve: Tutorial diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx new file mode 100644 index 00000000000..f98b71ee493 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 2 +--- + +# Criando um projeto + +## Geração de Projeto + +Agora que o CLI está instalado, você pode gerar um novo projeto usando o comando `wails init`. + +Escolha seu framework favorito: + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + Generate a Svelte project using JavaScript with:

+ + wails init -n myproject -t svelte + +If you would rather use TypeScript:
+ + wails init -n myproject -t svelte-ts + +
+ + Generate a React project using JavaScript with:

+ + wails init -n myproject -t react + +If you would rather use TypeScript:
+ + wails init -n myproject -t react-ts + +
+ + Generate a Vue project using JavaScript with:

+ + wails init -n myproject -t vue + +If you would rather use TypeScript:
+ + wails init -n myproject -t vue-ts + +
+ + Generate a Preact project using JavaScript with:

+ + wails init -n myproject -t preact + +If you would rather use TypeScript:
+ + wails init -n myproject -t preact-ts + +
+ + Generate a Lit project using JavaScript with:

+ + wails init -n myproject -t lit + +If you would rather use TypeScript:
+ + wails init -n myproject -t lit-ts + +
+ + Generate a Vanilla project using JavaScript with:

+ + wails init -n myproject -t vanilla + +If you would rather use TypeScript:
+ + wails init -n myproject -t vanilla-ts + +
+
+``` + +
+ +Há também [templates da comunidade](../community/templates.mdx) disponíveis que oferecem diferentes recursos e frameworks. + +Para ver as outras opções disponíveis, você pode executar `wails init -help`. Mais detalhes podem ser encontrados na [Referência da CLI](../reference/cli.mdx#init). + +## Layout do Projeto + +Os projetos Wails possuem o seguinte layout: + +``` +. +├── build/ +│ ├── appicon.png +│ ├── darwin/ +│ └── windows/ +├── frontend/ +├── go.mod +├── go.sum +├── main.go +└── wails.json +``` + +### Estrutura do projeto em execução + +- `/main.go` - A aplicação principal +- `/frontend/` - Arquivos do Frontend do projeto +- `/build/` - Diretório de compilação do projeto +- `/build/appicon.png` - O ícone da aplicação +- `/build/darwin/` - Arquivos do projeto específicos do Mac +- `/build/windows/` - Arquivos de projeto específicos do Windows +- `/wails.json` - A configuração do projeto +- `/go.mod` - O arquivo de módulos do Go +- `/go.sum` - O arquivo de checagem dos módulos do Go + +O diretório `frontend` não tem nada específico para o Wails e pode ser qualquer projeto frontend de sua escolha. + +O diretório `build` é usado durante o processo de compilação. Esses arquivos podem ser atualizados para personalizar suas compilações. Se arquivos forem removidos do diretório de compilação, as versões padrão serão restauradas. + +O nome do módulo padrão em `go.mod` é "changeme". Você deveria mudar isso para algo mais apropriado. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx new file mode 100644 index 00000000000..33400cdfdbf --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx @@ -0,0 +1,90 @@ +--- +sidebar_position: 1 +--- + +# Instalação + +## Plataformas Suportadas + +- Windows 10/11 AMD64/ARM64 +- MacOS 10.13+ AMD64 +- MacOS 11.0+ ARM64 +- Linux AMD64/ARM64 + +## Dependências + +O Wails tem várias dependências comuns que são necessárias antes da instalação: + +- Go 1.18+ +- NPM (Node 15+) + +### Go + +Baixe o Go direto da [página de download do Go](https://go.dev/dl/). + +Certifique-se de seguir as [instruções oficiais de instalação do Go](https://go.dev/doc/install). Você também precisará garantir que sua `variável de ambiente PATH` também inclua o caminho para o seu diretório `~/go/bin`. Reinicie seu terminal e faça as seguintes verificações: + +- Verificar se o Go está instalado corretamente: `go version` +- Cheque se `~/go/bin` está nas suas variáveis de ambiente `echo $PATH | grep go/bin` + +### NPM + +Baixe o NPM da [Página de downloads do Node](https://nodejs.org/en/download/). É melhor usar o último lançamento, pois é isso que costumamos testar. + +Execute `npm --version` para verificar. + +## Dependências específicas da plataforma + +Você também precisará instalar as dependências específicas da plataforma: + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + Wails requires that the xcode command line tools are installed. This can be + done by running xcode-select --install. + + + Wails requires that the WebView2 runtime is installed. Algumas instalações do Windows já terão isto instalado. Você pode conferir usando o comando do wails doctor. + + + Linux requires the standard gcc build tools plus libgtk3 and libwebkit. Ao invés de listar uma tonelada de comandos para diferentes distros, os Wails podem tentar determinar quais são os comandos de instalação para sua distribuição específica. Execute o wails doctor após a instalação para ser mostrado como instalar as dependencias. Se o seu gerenciador de destro/pacote não for suportado, por favor, consulte o guia Adicionar Distro do Linux. + + +``` + +## Dependências opcionais + +- [UPX](https://upx.github.io/) para comprimir suas aplicações. +- [NSIS](https://wails.io/docs/guides/windows-installer/) for generating Windows installers. + +## Instalando Wails + +Execute `instale github.com/wailsapp/wails/v2/cmd/wails@latest` para instalar a CLI do Wails. + +Note: If you get an error similar to this: + +```shell +....\Go\pkg\mod\github.com\wailsapp\wails\v2@v2.1.0\pkg\templates\templates.go:28:12: pattern all:ides/*: no matching files found +``` +please check you have Go 1.18+ installed: +```shell +go version +``` + +## Verificação do sistema + +Ao executar `wails doctor ` verificará quais dependências estão instaladas corretamente. Caso contrário, aconselhará sobre o que está em falta e ajudará a corrigir quaisquer problemas. + +## O comando `wail` parece estar faltando? + +Se o sistema está relatando que o comando `wail` está faltando, certifique-se de ter seguido o guia de instalação corretamente. Normalmente, isso significa que o diretório `go/bin` no diretório do seu usuário não está na variável do ambiente `PATH`. Você normalmente também precisará fechar e reabrir qualquer prompt de comando aberto para que as alterações no ambiente feitas pelo instalador sejam refletidas no prompt de comando. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx new file mode 100644 index 00000000000..cae0d7f95a5 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx @@ -0,0 +1,14 @@ +# Angular + +Embora as Wails não tenham um modelo angular, é possível usar Angular com Wails. + +## Modo Desenvolvedor + +Para que o modo de desenvolvimento funcione com Angular, você precisa adicionar o seguinte ao seu `wails.json`: + +```json + "frontend:build": "npx ng build", + "frontend:install": "npm install", + "frontend:dev:watcher": "npx ng serve", + "frontend:dev:serverUrl": "http://localhost:4200", +``` \ No newline at end of file diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx new file mode 100644 index 00000000000..f81eae7fa8d --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx @@ -0,0 +1,215 @@ +# Desenvolvimento de Aplicações + +Não existem regras rígidas e rápidas para o desenvolvimento das aplicações com o "Wails”, mas existem algumas orientações básicas. + +## Configurar Aplicação + +O padrão usado pelos templates padrão é que `main.go` é usado para configurar e executar a aplicação, enquanto `app.go` é usado para definir a lógica da aplicação. + +O arquivo `app.go` definirá uma struct que tem 2 métodos que funcionam como hooks na aplicação principal: + +```go title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} +``` + +- O método `startup` é chamado assim que as Wails alocam os recursos de que precisa e é um bom lugar para a criação de recursos configurando ouvintes de eventos e qualquer outra coisa que o aplicativo precise na inicialização. É dado a ele um `context.Context` que é geralmente salvo em um campo struct. Este contexto é necessário para chamar o [runtime](../reference/runtime/intro.mdx). Se este método retornar um erro, o aplicativo será encerrado. No modo de desenvolvimento, o erro será exibido no console. + +- O método de `shutdown` será chamado pelo Wails logo no final do processo de encerramento. Este é um bom lugar para limpar memória e executar qualquer tarefa encerrada. + +O arquivo `main.go` geralmente consiste de uma única chamada para `wails.Run()`, que aceita a configuração da aplicação. O padrão usado pelos templates é o antes da chamada para `wails.Run()`, uma instância do struct definido no aplicativo `app. o` é criado e salvo em uma variável chamada `app`. Essa configuração é onde adicionamos os nossos callbacks: + +```go {3,9,10} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +Mais informações sobre os hooks do ciclo de vida da aplicação podem ser encontradas [aqui](../howdoesitwork.mdx#application-lifecycle-callbacks). + +## Métodos de vínculo + +É provável que você queira chamar métodos Go do frontend. Isso normalmente é feito adicionando métodos públicos ao a struct já definida no `app.go`: + +```go {16-18} title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +Na configuração principal do aplicativo, a tecla `Bind` é onde podemos dizer aos Wails o que queremos vincular: + +```go {11-13} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +Isso vinculará todos os métodos públicos em nosso `App` de construção (isso nunca vinculará os métodos de inicialização e desligação). + +### Lidando com contexto quando vincular várias structs + +Se você quiser vincular métodos para várias structs , mas deseja que cada structs mantenha uma referência ao contexto para que você possa usar as funções de tempo de execução, um bom padrão é passar o contexto do método `OnStartup` para suas instâncias de construção : + +```go +func main() { + + app := NewApp() + otherStruct := NewOtherStruct() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: func(ctx context.Context){ + app.SetContext(ctx) + otherStruct.SetContext(ctx) + }, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + otherStruct + }, + }) + if err != nil { + log.Fatal(err) + } +} +``` + +Mais informações sobre isso podem ser encontradas [aqui](../howdoesitwork.mdx#method-binding). + +## Menu da aplicação + +O Wails suporta adicionar um menu à sua aplicação. Isso é feito passando uma [struct](../reference/menus.mdx#menu) de menu para a configuração da aplicação. É comum o uso de um método que retorna um Menu, e ainda mais comum que seja um método na struct `App` usada para hooks de ciclo de vida. + +```go {11} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Menu: app.menu(), + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +## Assets + +A grande coisa do jeito que o Wails v2 lida com assets é que não o faz! A única coisa que você precisa fazer no Wails é um `embed.FS`. A forma como se chega a isso depende inteiramente de você. Você pode usar arquivos html/css/js como o modelo vanilla. Você pode ter um sistema de compilação complicado, isso não importa. + +Quando `wails build` é executado, ele vai verificar o arquivo do projeto `wails.json` na raiz do projeto. Há duas chaves no arquivo do projeto que são lidas: + +- "frontend:install" +- "frontend:build" + +O primeiro, se dado, será executado no diretório `frontend` para instalar os módulos do Node. O segundo, se dado, será executado no diretório `frontend` para realizar o build do projeto frontend. + +Se essas duas chaves não são dadas, então as Wails não faz absolutamente nada com a frontend. É apenas esperando o `embed.FS`. + +### AssetsHandler + +Um aplicativo Wails v2 pode opcionalmente definir um `http.Handler` nas opções `options.App`, que permite o gancho do AssetServer criar arquivos em tempo real ou processe solicitações POST/PUT. Solicitações GET sempre são tratadas primeiramente pelos `assets` FS. Se o FS não encontrar o arquivo solicitado, a solicitação será encaminhada para `http.Handler` para servir. Qualquer requisição que não seja o GET será diretamente processada pelo `AssetsHandler` se especificado. Também é usar apenas o `AssetsHandler` por especificação é `nil` como a opção `Assets`. + +## Servidor de Desenvolvedor nativo + +Executar `wails dev` iniciará o servidor de desenvolvimento que também iniciará um observador de arquivos no seu diretório de projeto. Por padrão, se qualquer arquivo for alterado, verifica-se se era um arquivo da aplicação (padrão: `.go`, configurável com `-e` flag). Se foi, então ele irá reconstruir sua aplicação e reiniciá-la. Se o arquivo alterado estiver nos assets, emitirá uma recarga após um curto período de tempo. + +O servidor de desenvolvimento utiliza uma técnica chamada "debwaring" que significa que não recarrega imediatamente, como pode haver vários arquivos alterados em um curto período de tempo. Quando um gatilho ocorre, ele espera por uma quantidade de tempo definida antes de emitir um recarregamento. Se outro gatilho acontecer, ele será redefinido para esperar novamente. Por padrão, esse valor é de `100ms`. Se este valor não funcionar para o seu projeto, ele pode ser configurado usando a flag `-debounce`. Se usado, este valor será salvo na configuração do seu projeto e se tornará o padrão. + +## Servidor de Desenvolvedor Externo + +Alguns frameworks vêm com seu próprio servidor ao vivo, no entanto, eles não serão capazes de tirar proveito das ligações Go/Wails. Neste cenário, é melhor executar um script de observador que reconstrui o projeto no diretório build, que Wails estará assistindo. Por exemplo, veja o modelo padrão do svelte que usa [rollup](https://rollupjs.org/guide/en/). + +### Criar Aplicativo React + +O processo para um projeto Create-React-App é um pouco mais complicado. Para ajudar o frontend a recarregar ao vivo a seguinte configuração precisa ser adicionado ao seu `wails.json`: + +```json + "frontend:dev:watcher": "yarn start", + "frontend:dev:serverUrl": "http://localhost:3000", +``` + +O comando `frontend: dev:watcher` iniciará o servidor de desenvolvimento Create-React-App (hospedado na porta `3000` normalmente). O comando `frontend: dev:serverUrl` e instrui a Wails a servir assets do servidor de desenvolvimento ao carregar o frontend em vez de a partir da pasta de compilação. Além do acima acima o `index.html` precisa ser atualizado com o seguinte: + +```html + + + + + +``` + +Isso é necessário pois o comando do observador que reconstrui o frontend impede que o Wails injete os scripts necessários. Isso contorna esse problema garantindo os scripts são sempre injetados. Com esta configuração, `ondas de desenvolvimento` pode ser executado, o que irá construir adequadamente o frontend e o backend com o carregamento de quente ativado. Além disso, ao acessar o aplicativo a partir de um navegador, as ferramentas de desenvolvedor do React agora podem ser usadas em uma versão não minificada do aplicativo para simplificar depuração. Finalmente, para compilações mais rápidas, `wail dev -s` pode ser executado para ignorar o edifício padrão do frontend pelas Wails, pois este é um passo desnecessário. + +## Go Module + +Os modelos padrão do Wails geram um arquivo `go.mod` que contém o nome do módulo "changeme". Você deve alterar isto para algo mais apropriado após a geração do projeto. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx new file mode 100644 index 00000000000..fd81a974d04 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx @@ -0,0 +1,66 @@ +# Crossplatform build with Github Actions + +To build a Wails project for all the available platforms, you need to create an application build for each operating system. One effective method to achieve this is by utilizing GitHub Actions. + +An action that facilitates building a Wails app is available at: +https://github.com/dAppServer/wails-build-action + +In case the existing action doesn't fulfill your requirements, you can select only the necessary steps from the source: +https://github.com/dAppServer/wails-build-action/blob/main/action.yml + +Below is a comprehensive example that demonstrates building an app upon the creation of a new Git tag and subsequently uploading it to the Actions artifacts: + +```yaml +name: Wails build + +on: + push: + tags: + # Match any new tag + - '*' + +env: + # Necessary for most environments as build failure can occur due to OOM issues + NODE_OPTIONS: "--max-old-space-size=4096" + +jobs: + build: + strategy: + # Failure in one platform build won't impact the others + fail-fast: false + matrix: + build: + - name: 'App' + platform: 'linux/amd64' + os: 'ubuntu-latest' + - name: 'App' + platform: 'windows/amd64' + os: 'windows-latest' + - name: 'App' + platform: 'darwin/universal' + os: 'macos-latest' + + runs-on: ${{ matrix.build.os }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Build wails + uses: dAppServer/wails-build-action@v2.2 + id: build + with: + build-name: ${{ matrix.build.name }} + build-platform: ${{ matrix.build.platform }} + package: false + go-version: '1.20' +``` + +This example offers opportunities for various enhancements, including: + +- Caching dependencies +- Code signing +- Uploading to platforms like S3, Supbase, etc. +- Injecting secrets as environment variables +- Utilizing environment variables as build variables (such as version variable extracted from the current Git tag) diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx new file mode 100644 index 00000000000..e86b651845d --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx @@ -0,0 +1,204 @@ +# Custom Protocol Scheme association + +Custom Protocols feature allows you to associate specific custom protocol with your app so that when users open links with this protocol, +your app is launched to handle them. This can be particularly useful to connect your desktop app with your web app. +In this guide, we'll walk through the steps to implement custom protocols in Wails app. + +## Set Up Custom Protocol Schemes Association: + +To set up custom protocol, you need to modify your application's wails.json file. +In "info" section add a "protocols" section specifying the protocols your app should be associated with. + +For example: + +```json +{ + "info": { + "protocols": [ + { + "scheme": "myapp", + "description": "My App Protocol", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------ | +| scheme | Custom Protocol scheme. e.g. myapp | +| description | Windows-only. The description. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open custom protocol with your app, the system will launch your app and call the `OnUrlOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnUrlOpen: func(url string) { println(url) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows Custom Protocol Schemes is supported only with NSIS installer. During installation, the installer will create a +registry entry for your schemes. When you open url with your app, new instance of app is launched and url is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there (note that `%u` is important in Exec). Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=x-scheme-handler/myapp; +``` + +2. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +``` + +3. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with custom protocol scheme. When you open url with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx new file mode 100644 index 00000000000..627bbeb5e36 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx @@ -0,0 +1,136 @@ +# Recursos Dinâmicos + +Se você deseja carregar ou gerar assets para seu frontend de forma dinâmica, você pode conseguir isso usando a opção [AssetsHandler](../reference/options#assetshandler). O AssetsHandler é um `http.Handler` genérico que irá ser chamado para qualquer solicitação não GET no servidor de ativos e para solicitações GET que não podem ser atendidas pelo ativos agrupados porque o arquivo não foi encontrado. + +Ao instalar um AssetsHandler personalizado, você pode servir seus próprios assets usando um servidor de arquivos personalizado. + +## Exemplo + +Em nosso projeto de exemplo, vamos criar um gerenciador de arquivos simples que irá carregar arquivos fora do disco: + +```go title=main.go {17-36,49} +package main + +import ( + "embed" + "fmt" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "net/http" + "os" + "strings" +) + +//go:embed all:frontend/dist +var assets embed.FS + +type FileLoader struct { + http.Handler +} + +func NewFileLoader() *FileLoader { + return &FileLoader{} +} + +func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) { + var err error + requestedFilename := strings.TrimPrefix(req.URL.Path, "/") + println("Requesting file:", requestedFilename) + fileData, err := os.ReadFile(requestedFilename) + if err != nil { + res.WriteHeader(http.StatusBadRequest) + res.Write([]byte(fmt.Sprintf("Could not load file %s", requestedFilename))) + } + + res.Write(fileData) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "helloworld", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: NewFileLoader(), + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 255}, + OnStartup: app.startup, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +Quando executarmos o aplicativo no modo de desenvolvimento usando `wail dev`, veremos a seguinte saída: + +``` +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' failed, using AssetHandler +Requesting file: favicon.ico +``` + +Como você pode ver, o manipulador de assets é chamado quando o servidor de assets padrão não consegue servir o arquivo `favicon.ico`. + +Se você clicar com o botão direito no aplicativo principal e selecionar "inspeção" para abrir as devtools, você pode testar esta função digitando o seguinte no console: + +``` +let response = await fetch('does-not-exist.txt'); +``` + +Isto irá gerar um erro no devtools. Podemos ver que o erro é o que esperamos, retornado por nosso manipulador de ativos personalizados: + +```mdx-code-block +

+ +

+``` + +No entanto, se requisitarmos `go.mod`, veremos a seguinte saída: + +```mdx-code-block +

+ +

+``` + +Esta técnica pode ser usada para carregar imagens diretamente para a página. Se atualizarmos nosso modelo padrão do vanilla e substituirmos a imagem do logotipo: + +```html + +``` + +com: + +```html + +``` + +Veremos então o seguinte: + +```mdx-code-block +

+ +

+``` + +:::warning + +Expor seu sistema de arquivos desta forma é um risco à segurança. É recomendável que você gerencie corretamente o acesso ao seu sistema de arquivos. + +::: diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx new file mode 100644 index 00000000000..167955b12d7 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx @@ -0,0 +1,244 @@ +# File Association + +File association feature allows you to associate specific file types with your app so that when users open those files, +your app is launched to handle them. This can be particularly useful for text editors, image viewers, or any application +that works with specific file formats. In this guide, we'll walk through the steps to implement file association in Wails app. + +## Set Up File Association: + +To set up file association, you need to modify your application's wails.json file. +In "info" section add a "fileAssociations" section specifying the file types your app should be associated with. + +For example: + +```json +{ + "info": { + "fileAssociations": [ + { + "ext": "wails", + "name": "Wails", + "description": "Wails Application File", + "iconName": "wailsFileIcon", + "role": "Editor" + }, + { + "ext": "jpg", + "name": "JPEG", + "description": "Image File", + "iconName": "jpegFileIcon", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | +| ext | The extension (minus the leading period). e.g. png | +| name | The name. e.g. PNG File | +| iconName | The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows | +| description | Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open file (or files) with your app, the system will launch your app and call the `OnFileOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnFileOpen: func(filePaths []string) { println(filestring) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows file association is supported only with NSIS installer. During installation, the installer will create a +registry entry for your file associations. When you open file with your app, new instance of app is launched and file path is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there. Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=application/x-wails;application/x-test +``` + +2. Create mime types file. Example: + +```xml + + + + Wails Application File + + + +``` + +3. Create icons for your file types. SVG icons are recommended. +4. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload mime types to register file associations +update-mime-database /usr/share/mime +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +# update icons +update-icon-caches /usr/share/icons/* +``` + +5. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ./application-wails-mime.xml + dst: /usr/share/mime/packages/application-x-wails.xml +- src: ./application-test-mime.xml + dst: /usr/share/mime/packages/application-x-test.xml +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with specified file types. When you open file with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx new file mode 100644 index 00000000000..430f53a6afc --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx @@ -0,0 +1,87 @@ +# Aplicações sem frames + +O Wails suporta aplicativos que não possuem frames. Isso pode ser conseguido usando o campo [sem frameless](../reference/options.mdx#frameless) no [Application Options](../reference/options.mdx#application-options). + +Wails oferece uma solução simples para arrastar a janela: qualquer elemento HTML que tenha o estilo CSS `--wails-draggable:drag` irá atuar como uma "alça de arrastar". Esta propriedade se aplica a todos os elementos filhos. Se você precisar indicar que um elemento aninhado não deve arrastar, então use o atributo '--wails-draggable:no-drag' nesse elemento. + +```html + + + + + + + +
+ + +
+
+ + + + +``` + +Para alguns projetos, usar uma variável CSS pode não ser possível devido a um estilo dinâmico. Neste caso, você pode usar o aplicativo `CSSDragProperty` e `CSSDragValue` opções para definir uma propriedade e valor que serão usados para indicar regiões arrastáveis: + +```go title=main.go +package main + +import ( + "embed" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "alwaysontop", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Frameless: true, + CSSDragProperty: "widows", + CSSDragValue: "1", + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +```html title=index.html + + + + + + alwaysontop + + +
+ + + +``` + +:::info Tela Cheia + +Se você permitir que seu aplicativo vá para tela cheia, esta funcionalidade de arrastar será desativada. + +::: diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx new file mode 100644 index 00000000000..aade2b7f4cc --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx @@ -0,0 +1,72 @@ +# Frontend + +## Injeção de script + +Quando Wails serve a página `index.html`, por padrão injetará duas entradas de escript na ``tag para carregar `/wails/ipc.js` e `/wails/runtime.js`. Esses arquivos instalam o bindings e o tempo de execução, respectivamente. + +O código abaixo mostra onde estas são injetadas por padrão: + +```html + + + injection example + + + + + + + +
Please enter your name below 👇
+
+ + +
+ + + + +``` + +### Sobrescrevendo a injeção de script padrão + +Para oferecer mais flexibilidade aos desenvolvedores, há uma meta tag que pode ser usada para personalizar este comportamento: + +```html + +``` + +As configurações são as seguintes: + +| Valor | Descrição | +| ------------------- | ---------------------------------------------- | +| noautoinjectruntime | Desativa a auto-injeção no `/wails/runtime.js` | +| noautoinjectipc | Desativa a autoinjeção no `/wails/ipc.js` | +| noautoinject | Desativa todas as autoinjeções de scripts | + +Várias opções podem ser usadas, desde que sejam separadas por vírgulas. + +Este código é perfeitamente válido e opera o mesmo que a versão da auto-injeção: + +```html + + + injection example + + + + + + +
Please enter your name below 👇
+
+ + +
+ + + + + + +``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx new file mode 100644 index 00000000000..fdb83a6adf3 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx @@ -0,0 +1,127 @@ +# IDEs + +O Wails pretende proporcionar uma grande experiência de desenvolvimento. Para atingir isso, agora suportamos a geração de configuração específica de IDE para fornecer uma configuração de projeto mais suave. + +Atualmente, nós suportamos o [Visual Studio Code](https://code.visualstudio.com/) mas buscamos oferecer suporte a outros IDEs, como o Goland. + +## Visual Studio Code + +```mdx-code-block +

+ +

+``` + +Ao gerar um projeto usando a `-ide vscode` flag, arquivos IDE serão criados juntamente com os outros arquivos do projeto. Estes arquivos são colocados no diretório `.vscode` e fornecem a configuração correta para depurar seu aplicativo. + +Os 2 arquivos gerados são `tasks.json` e `launch.json`. Abaixo estão os arquivos gerados para o projeto vanilla padrão: + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/myproject.exe" + ] + } + ] +} +``` + +```json title="launch.json" +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Wails: Debug myproject", + "type": "go", + "request": "launch", + "mode": "exec", + "program": "${workspaceFolder}/build/bin/myproject.exe", + "preLaunchTask": "build", + "cwd": "${workspaceFolder}", + "env": {} + } + ] +} +``` + +### Configurando os passos de instalação e compilação + +O arquivo `tasks.json` é simples para o projeto padrão, já que não há nenhuma etapa de instalação em que `npm` ou `npm run build` seja necessário. Para projetos que tenham uma etapa de build de front-end, como o modelo do Svelte, precisaríamos editar `tasks.json` e adicionar os passos de instalação e compilação: + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "npm install", + "type": "npm", + "script": "install", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "npm run build", + "type": "npm", + "script": "build", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/vscode.exe" + ], + "dependsOn": ["npm install", "npm run build"] + } + ] +} +``` + +:::info Melhoria Futura + +No futuro, esperamos gerar um `tasks.json` que inclui os passos de instalação e compilação automaticamente. + +::: diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx new file mode 100644 index 00000000000..0241bdb5a65 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx @@ -0,0 +1,103 @@ +# Suporte a Distros Linux + +## Visão geral + +O Wails oferece suporte Linux, mas fornecer instruções de instalação para todas as distribuições disponíveis é uma tarefa impossível. Em vez disso, a Wails tenta determinar se os pacotes que você precisa para desenvolver aplicações estão disponíveis através do gerenciador de pacote do seu sistema. Atualmente, suportamos os seguintes gestores de pacotes: + +- apt +- dnf +- emerge +- eopkg +- nixpkgs +- pacman +- zypper + +## Adicionando nomes de pacotes + +Pode haver circunstâncias em que sua distro use um dos gerentes de pacote suportados, mas o nome do pacote é diferente. Por exemplo, você pode usar um derivado de Ubuntu, mas o nome do pacote para gtk pode ser diferente. Wails tenta encontrar o pacote correto iterando por meio de uma lista de nomes de pacotes. A lista de pacotes é armazenada no arquivo específico do gerenciador de pacotes no diretório `v2/internal/system/packagemanager`. No nosso exemplo, isso seria `v2/internal/system/packagemanager/apt.go`. + +Neste arquivo, a lista de pacotes são definidos pelo método `Packages()`: + +```go +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +Vamos supor que na nossa distração em linux, a `libgtk-3` é empacotada com o nome `lib-gtk3-dev`. Podemos adicionar suporte para isso adicionando a seguinte linha: + +```go {5} +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + {Name: "lib-gtk3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +## Adicionando novos gerenciadores de pacotes + +Para adicionar um novo gerenciador de pacotes, execute os seguintes passos: + +- Crie um novo arquivo em `v2/internal/system/packagemanager` chamado `.go`, onde `` é o nome do gerenciador de pacote. +- Defina uma struct que esteja em conformidade com a interface de gerenciador de pacotes definida em `pm.go`: + +```go +type PackageManager interface { + Name() string + Packages() packagemap + PackageInstalled(*Package) (bool, error) + PackageAvailable(*Package) (bool, error) + InstallCommand(*Package) string +} +``` + +- `Name()` deve retornar o nome do gerenciador de pacotes +- `Packages()` deve retornar um `packagemap`, que fornece nomes de arquivo de candidatos para dependências +- `PackageInstalled()` deve retornar `true` se o pacote for instalado +- `PackageAvailable()` deve retornar `true` se o pacote fornecido não estiver instalado, mas disponível para instalação +- `InstallCommand()` deve retornar o comando exato para instalar o nome do pacote dado + +Dê uma olhada no código de outros gerenciadores de pacotes para ter uma ideia de como isto funciona. + +:::info Lembre-se + +Se você adicionar suporte para um novo gerenciador de pacotes, não se esqueça de também atualizar esta página! + +::: diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx new file mode 100644 index 00000000000..a975968f316 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx @@ -0,0 +1,18 @@ +# Linux + +Esta página possui vários guias relacionados ao desenvolvimento de aplicativos Wails para Linux. + +## A tag de vídeo não ativa o evento "ended" + +Ao usar uma tag de vídeo, o evento "ended" não é acionado quando o vídeo terminar de ser reproduzido. Este é um erro no WebkitGTK, no entanto, você pode usar a seguinte solução alternativa para corrigi-lo: + +```js +videoTag.addEventListener("timeupdate", (event) => { + if (event.target.duration - event.target.currentTime < 0.2) { + let ended = new Event("ended"); + event.target.dispatchEvent(ended); + } +}); +``` + +Fonte: [Lyimmi](https://github.com/Lyimmi) no [fórum de discussões](https://github.com/wailsapp/wails/issues/1729#issuecomment-1212291275) diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx new file mode 100644 index 00000000000..4ba06231463 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx @@ -0,0 +1,55 @@ +# Desenvolvimento Local + +## Visão geral + +Os dispositivos estão em constante desenvolvimento e novos lançamentos são regularmente "marcados". Isso geralmente acontece quando todo o código no `master` foi testado e confirmado funcionando. Se você precisar de uma correção de bug ou recurso que ainda não foi lançado, é possível usar a versão mais recente "bleeding edge" seguindo as seguintes etapas: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails/v2/cmd/wails` +- `go install` + +NOTA: O diretório para o qual você clonou o projeto será agora chamado de "clonedir". + +A CLI do Wails estará na versão mais recente. + +### Atualizando seu projeto + +Para atualizar projetos para usar a versão mais recente da biblioteca Wails, atualize o `do projeto. od` e certifique-se que a seguinte linha está no final do arquivo: + +`replace github.com/wailsapp/wails/v2 => ` + +Exemplo: + +Windows: `substitua github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2` + +Em 'nix: `substitui github.com/wailsapp/wails/v2 => /home/me/projects/wails/v2` + +Para reverter para uma versão estável, execute: + +`go install github.com/wailsapp/wails/v2/cmd/wails@latest` + +## Testando uma Branch + +Se você deseja testar um branch, siga as instruções acima, mas certifique-se de alternar o branch que você deseja testar antes de instalar: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails` +- `git checkout -b branch-to-test --track origin/branch-to-test` +- `cd v2/cmd/wails` +- `go install` + +Certifique-se de [atualizar seu projeto](#updating-your-project) conforme descrito acima. + +## Testando uma PR + +Se você deseja testar um branch, siga as instruções acima, mas certifique-se de alternar o branch que você deseja testar antes de instalar. Por favor, substitua `[IDofThePR]` pelo ID do PR mostrado no github.com: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails` +- `git fetch -u origin pull/[IDofThePR]/head:test/pr-[IDofThePR]` +- `git checkout test/pr-[IDofThePR]` +- `git reset --hard HEAD` +- `cd v2/cmd/wails` +- `go install` + +Certifique-se de [atualizar seu projeto](#updating-your-project) conforme descrito acima. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx new file mode 100644 index 00000000000..4b7b589c1a4 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx @@ -0,0 +1,97 @@ +# Guia para Mac App Store + +Esta página dá uma breve visão geral de como enviar seu App Wails para a Mac App Store. + +## Pré-requisitos + +- Você precisará ter uma conta para o Apple Develop. Encontre mais informações no site [do Programa de Desenvolvedor Apple](https://developer.apple.com/support/compare-memberships/) +- Você precisará ter seus Certificados, Identificadores e App criados no portal de desenvolvimento. Mais sobre isto abaixo +- Ferramentas de linha de comando Xcode precisarão ser instaladas na sua máquina local + +#### Criar certificados e identificadores + +1. Vá para sua [Conta de desenvolvedor Apple](https://developer.apple.com/account/) +2. Sob `Certificados, Identificadores & Perfis`, clique em `Identificadores` e Registrar um Novo App ID. Use o formato (com.exemplo.app) +3. Sob a mesma página, clique `Certificados` e gere novos Certificados para a Distribuição da Loja de Aplicativos Mac. Baixe-os e importe os certificados para o Keychain em sua máquina local. + +#### Criar Envio de App + +1. Ir para [App Store Connect Site](https://appstoreconnect.apple.com/apps) +2. Registre um novo aplicativo e vincule o ID do pacote que você criou no passo anterior +3. Preencher seu aplicativo com as capturas de tela corretas, descrições, etc. conforme exigido pela Apple +4. Criar uma nova versão do seu aplicativo + +#### Criar perfil de provisionamento +1. Vá para a página [Apple Developer Profiles](https://developer.apple.com/account/resources/profiles/list) +2. Adicionar um novo perfil de provisionamento para Mac App Store de distribuição +3. Defina o tipo de perfil como Mac e selecione o ID do aplicativo criado acima +4. Selecione o certificado de Distribuição de Aplicativos Mac +5. Nomeie o Perfil de Provisão incorporado e baixe o perfil criado. + +## Guia para Mac App Store + +#### Ativar a App Sandbox da Apple + +Os aplicativos enviados para Mac App Store devem ser executados na [App Sandbox](https://developer.apple.com/app-sandboxing/) da Apple. Você deve criar um arquivo `entitlements.plist` para que isso funcione. A recomendação é criar este arquivo sob este caminho `{PROJECT_DIR}/build/darwin/entitlements.plist`. + +**Exemplo de arquivo de direitos** + +Este é um exemplo de titularidade de arquivo do aplicativo [RiftShare](https://github.com/achhabra2/riftshare). Para referência, por favor coloque os direitos que seu aplicativo exigir. Consulte [este site](https://developer.apple.com/documentation/bundleresources/entitlements) para obter mais informações. Você precisará substituir a ID da Equipe e o Nome da Aplicação pelos que você se registrou acima. + +```xml title="entitlements.plist" + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + com.apple.application-identifier + TEAM_ID.APP_NAME + com.apple.developer.team-identifier + TEAM_ID + + +``` + +**Adicionar Perfil de Provisão Embutido** O Perfil de Provisionamento criado acima precisa ser adicionado à raiz da aplicação. Precisa ser nomeado como embedded.provisionprofile. + +#### Construa e assine o Pacote de Aplicativos + +O seguinte é um exemplo de script para construir e assinar seu aplicativo para o envio da Mac App Store. Ele presume que você está executando o script do diretório do seu projeto raiz. + +Observe que os certificados para a assinatura do aplicativo e a assinatura do instalador são diferentes. Certifique-se de que ambos são importados para o Keychain. Encontre as sequências de caracteres no Keychain e insira-as abaixo. Preencha os nomes do seu certificado e o nome do app abaixo. Executar o seguinte script irá gerar um arquivo `assinado app.pkg` no diretório raiz do seu aplicativo. + +```bash title="macappstore-build.sh" +#!/bin/bash + +APP_CERTIFICATE="3rd Party Mac Developer Application: YOUR NAME (CODE)" +PKG_CERTIFICATE="3rd Party Mac Developer Installer: YOUR NAME (CODE)" +APP_NAME="YourApp" + +wails build -platform darwin/universal -clean + +cp ./embedded.provisionprofile "./build/bin/$APP_NAME.app/Contents" + +codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist ./build/bin/$APP_NAME.app + +productbuild --sign "$PKG_CERTIFICATE" --component ./build/bin/$APP_NAME.app /Applications ./$APP_NAME.pkg +``` + +#### Enviar pacote de aplicativos + +Você precisará enviar o arquivo do pacote gerado e associá-lo à sua Aplicação antes de poder enviá-lo para revisão. + +1. Baixe o [aplicativo Transporter](https://apps.apple.com/us/app/transporter/id1450874784) na Mac App Store +2. Abra e inicie sessão com a sua Apple ID +3. Clique no sinal + e selecione o arquivo `APP_NAME.pkg` que você gerou na etapa anterior. Carregar isto +4. Volte para [Loja de Apps Conectar](https://appstoreconnect.apple.com/apps) e navegue de volta para a submissão de seu aplicativo. Selecione a versão que você está pronto para disponibilizar na App Store. Em `Build` selecione o pacote que você enviou via Transporter. + +É isso! Agora você pode usar o site para enviar seu Aplicativo para análise. Após alguns dias úteis, se tudo correr bem, você verá seu App ao vivo na Mac App Store. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx new file mode 100644 index 00000000000..f3142438d76 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx @@ -0,0 +1,95 @@ +# Compilações manuais + +O CLI Wails faz um trabalho pesado pelo projeto, mas às vezes é desejável construir o seu projeto manualmente. Este documento discutirá as diferentes operações da CLI e a forma como isso pode ser conseguido de diferentes maneiras. + +## Processo de compilação + +Quando `wails build` ou `wails dev` são usados, o Wails CLI executa um processo de compilação comum: + + - Instalar dependências frontend + - Construir projeto frontend + - Gerar mídias de construção + - Compilar aplicação + - [optional] Comprimir o aplicativo + +### Instalar dependências frontend + +#### Passos CLI + +- Se a flag `-s` for dada, esta etapa é ignorada +- Verifica `wails.json` para ver se há um comando de instalação na chave `frontend:install` +- Se não houver, ela pula esta etapa +- Se houver, ele verifica se `package.json` existe no diretório do frontend. Se não existir, pula esta etapa +- Uma soma MD5 é gerada a partir do conteúdo do arquivo `package.json` +- Verifica a existência de `package.json.md5` e, se existir, irá comparar o conteúdo dele (uma soma MD5) com o gerado para ver se o conteúdo mudou. Se eles forem iguais, este passo é ignorado +- Se `package.json.md5` não existir, será criado usando a soma MD5 gerada +- Se uma compilação é necessária agora, ou a `node_modules` não existe, ou a flag `-f` é dada, o comando de instalação é executado no diretório frontend + +#### Passos manuais + +Esta etapa pode ser feita na linha de comando ou um script com o `npm install`. + +### Construir projeto frontend + +#### Wails CLI + +- Se a flag `-s` for dada, esta etapa é ignorada +- Verifica `wails.json` para ver se há um comando de compilação na chave `frontend:build` +- Se não houver, ela pula esta etapa +- Se houver, ele é executado no diretório frontend + +#### Passos manuais + +Esta etapa poderia ser feita a partir da linha de comando ou um script com `npm run build` ou qualquer que seja o script de compilação do frontend. + +### Gerar mídias + +#### Wails CLI + +- Se a flag `-nopackage` estiver definida, este estágio será ignorado +- Se o arquivo `build/appicon.png` não existir, um arquivo padrão será criado +- Para Windows, consulte [Conjuntos para Windows](#windows) +- Se `build/windows/icon.ico` não existir, ele será criado a partir da imagem `build/appicon.png`. + +##### Windows + +- Se `build/windows/icon.ico` não existir, irá criá-lo a partir de `build/appicon. ng` usando tamanhos de ícones de 256, 128, 64, 48, 32 e 16. Isso é feito usando o [winicon](https://github.com/leaanthony/winicon). +- Se o arquivo `build/windows/.manifest` não existir, será criado a partir de uma versão padrão. +- Compila a aplicação como uma compilação de produção (acima) +- Usa [winres](https://github.com/tc-hib/winres) para empacotar o ícone e manifestar em um arquivo `.syso` pronto para vincular. + +#### Passos manuais + +- Crie `icon.ico` usando o [winicon](https://github.com/leaanthony/winicon) Ferramenta de CLI (ou qualquer outra ferramenta). +- Criar / Atualizar o arquivo de `.manifest` para sua aplicação +- Use o [winres CLI](https://github.com/tc-hib/go-winres) para gerar um arquivo `.syso`. + +### Compilar aplicação + +#### Wails CLI + +- Se o sinalizador `-clean` for fornecido, o diretório `build` é excluído e recriado +- Para `wails dev`, as seguintes bandeiras Go padrão são usadas: `-tags dev -gcflags "all=-N -l"` +- Para `wails build`, as seguintes flags padrão do Go são usadas: `-tags desktop,production -ldflags "-w -s"` + - No Windows, `-ldflags "-w -h -H windowsgui"` +- Tags adicionais passadas para o CLI usando `-tags` são adicionadas aos padrões +- Ldflags adicionais passadas para a CLI usando `-ldflags` são adicionados aos padrões +- A bandeira `-o` é passada +- O compilador Go especificado por `-compiler` será usado para compilação + +#### Passos manuais + +- Para compilação de desenvolvedores, o comando mínimo seria: `go build -tags dev -gcflags "all=-N -l"` +- Para a compilação de produção, o comando mínimo seria: `go build -tags desktop,production -ldflags "-w -s -H windowsgui"` +- Certifique-se de compilar no mesmo diretório que o arquivo `.syso` + +### Comprimir aplicativo + +#### Wails CLI + +- Se a flag `-upx` tiver sido dada, o programa `upx` será executado para comprimir o aplicativo com as configurações padrão +- Se `-upxflags` também for colado, essas flags são usadas em vez das padrão + +#### Passos manuais + +- Execute `upx [flags]` manualmente para comprimir o aplicativo. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx new file mode 100644 index 00000000000..a874b03f4f5 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx @@ -0,0 +1,191 @@ +# Migrando da v1 + +## Visão geral + +Wails v2 é uma mudança significativa em relação à v1. Este documento visa destacar as mudanças e as etapas na migração de um projeto existente. + +### Criando uma aplicação Cli + +Na v1, o aplicativo principal é criado usando `wails.CreateApp`, as ligações são adicionadas com `app.Bind` e, em seguida, o o aplicativo é executado usando `app.Run()`. + +Exemplo: + +```go title="v1" + app := wails.CreateApp(&wails.AppConfig{ + Title: "MyApp", + Width: 1024, + Height: 768, + JS: js, + CSS: css, + Colour: "#131313", + }) + app.Bind(basic) + app.Run() +``` + +Na v2, há apenas um único método, `wails.Run()`, que aceita as opções de aplicação [](../reference/options.mdx#application-options). + +```go title="v2" + err := wails.Run(&options.App{ + Title: "MyApp", + Width: 800, + Height: 600, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + basic, + }, + }) +``` + +### Mapeamento + +Na v1, foi possível vincular funções e estruturas arbitrárias. Em v2, foi simplificado apenas para estruturas vinculativas. As instâncias de construção que foram passadas anteriormente para o método `Bind()` na v1, estão agora especificados no campo `Vincular` do as opções de aplicação [](../reference/options.mdx#application-options): + +```go title="v1" + app := wails.CreateApp(/* options */) + app.Bind(basic) +``` + +```go title="v2" + err := wails.Run(&options.App{ + /* other options */ + Bind: []interface{}{ + basic, + }, + }) +``` + +Na v1, métodos vinculados estavam disponíveis para o frontend em `window.backend`. Isto mudou para `window.go` + +### Ciclo de vida da Aplicação + +Na v1, havia 2 métodos especiais em uma estrutura vinculada: `WailsInit()` e `WailsShutdown()`. Foi substituído por três ganchos de ciclo de vida como parte das [opções do aplicativo](../reference/options.mdx#application-options): + +- [OnStartup](../reference/options.mdx#onstartup) +- [OnShutdown](../reference/options.mdx#onshutdown) +- [OnDomReady](../reference/options.mdx#ondomready) + +Nota: [OnDomReady](../reference/options.mdx#ondomready) substitui o evento do sistema `wails:ready` na v1. + +Estes métodos podem ser funções padrão, mas uma prática comum é tê-los incluído numa estrutura: + +```go title="v2" + basic := NewBasicApp() + err := wails.Run(&options.App{ + /* Other Options */ + OnStartup: basic.startup, + OnShutdown: basic.shutdown, + OnDomReady: basic.domready, + }) +... +type Basic struct { + ctx context.Context +} +func (b *Basic) startup(ctx context.Context) { + b.ctx = ctx +} +... +``` + +### Tempo de execução + +O tempo de execução na v2 é muito mais rico que a v1 com suporte para menus, manipulação de janelas e melhores diálogos. A assinatura dos métodos mudou ligeiramente - consulte a [Referência de tempo de execução](../reference/runtime/intro.mdx). + +Na v1, o [runtime](../reference/runtime/intro.mdx) estava disponível através de uma struct passada para `WailsInit()`. Em v2, o tempo de execução foi movido para o seu próprio pacote. Cada método no tempo de execução leva o `context.Context` que é passado para o método [OnStartup](../reference/options.mdx#onstartup). + +```go title="Runtime Example" +package main + +import "github.com/wailsapp/wails/v2/pkg/runtime" + +type Basic struct { + ctx context.Context +} + +// startup is called at application startup +func (a *App) startup(ctx context.Context) { + a.ctx = ctx + runtime.LogInfo(ctx, "Application Startup called!") +} + +``` + +### Assets + +A _maior mudança_ na v2 é como os ativos são geridos. + +Na v1, os ativos foram passados via 2 opções de aplicativo: + +- `JS` - O JavaScript do aplicativo +- `CSS` - O CSS da aplicação + +Isso significava que a responsabilidade de gerar um único arquivo JS e CSS era do desenvolvedor. Isto exigia essencialmente a utilização de embalagens complicadas como o webpack. + +Na v2, Wails não faz suposições sobre seus ativos no frontend, como um servidor web. Todos os seus ativos de aplicação são passados para as opções de aplicação como um `embed.FS`. + +**Isso significa que não há necessidade de agrupar seus ativos, codificar imagens como Base64 ou experimente a arte obscura da configuração do bundler para usar fontes personalizadas**. + +Na inicialização, Wails verificará o `embed.FS` fornecido em busca de `index.html` e usará sua localização como caminho raiz para todos os outros ativos do aplicativo - assim como faria um servidor web. + +Exemplo: Uma aplicação tem o seguinte layout do projeto. Todos os arquivos finais são colocados no diretório `frontend/dist`: + +```shell +. +├── build/ +├── frontend/ +│ └── dist/ +│ ├── index.html +│ ├── main.js +│ ├── main.css +│ └── logo.svg +├── main.go +└── wails.json +``` + +Esses ativos podem ser usados pelo aplicativo simplesmente criando um `embed.FS`: + +```go title="Assets Example" +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + err := wails.Run(&options.App{ + /* Other Options */ + AssetServer: &assetserver.Options{ + Assets: assets, + }, + }) +} +``` + +Claro, empacotadores podem ser usados se você quiser. O único requisito é passar o diretório final de ativos do aplicativo para Wails usando um `embed.FS` no `Assets` chave das [opções do aplicativo](../reference/options.mdx#application-options). + +### Configuração do Projeto + +Na v1, a configuração do projeto foi armazenada no arquivo `project.json` na raiz do projeto. Na v2, a configuração do projeto é armazenada no arquivo `wails.json` na raiz do projeto. + +O formato do arquivo é ligeiramente diferente. Aqui está uma comparação: + +

+ +| v1 | v2 | Notes | +| ------------------ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | name | | +| description | | Removed | +| author / name | author / name | | +| author / email | author / email | | +| version | version | | +| binaryname | outputfilename | Changed | +| frontend / dir | | Removed | +| frontend / install | frontend:install | Changed | +| frontend / build | frontend:build | Changed | +| frontend / bridge | | Removed | +| frontend / serve | | Removed | +| tags | | Removed | +| | wailsjsdir | The directory to generate wailsjs modules | +| | assetdir | The directory of the compiled frontend assets for `dev` mode. Normalmente, isto é inferido e pode ser deixado vazio. | +| | reloaddirs | Lista separada por vírgulas de diretórios adicionais para observar alterações e acionar recarregamentos no modo `dev`. Isso só é necessário para algumas configurações de ativos mais avançadas. | + +

diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx new file mode 100644 index 00000000000..054ac263bd1 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx @@ -0,0 +1,25 @@ +# Botões do Mouse + +As Wails runtime interceptam cliques do mouse para determinar se uma janela precisa ser redimensionada ou uma janela precisa ser movida. Foi perguntado como detectar quando um clique do mouse ocorreu, porque `window.onclick` não relata os botões do mouse corretamente. O código a seguir mostra como detectar cliques do mouse: + +```javascript +window.addEventListener("mousedown", handleMouseButtonDown); + +function handleMouseButtonDown(event) { + if (event.button === 0) { + // left mouse button + } else if (event.button === 1) { + // middle mouse button + } else if (event.button === 2) { + // right mouse button + } else if (event.button === 3) { + // back mouse button + } else if (event.button === 4) { + // forward mouse button + } else { + // other mouse button + } +} +``` + +Reference: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx new file mode 100644 index 00000000000..d921a6a5fc2 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx @@ -0,0 +1,40 @@ +# Builds ofuscadas + +Wails inclui suporte para ofuscar a sua aplicação usando [garble](https://github.com/burrowers/garble). + +Para produzir uma compilação ofuscada, você pode usar o sinalizador `-obfuscate` com o comando `wails build`: + +```bash +wails build -obfuscated +``` + +Para personalizar a configuração de ofuscação, pode-se utilizar a flag: `-garbleargs`: + +```bash +wails build -obfuscated -garbleargs "-literals -tiny -seed=myrandomseed" +``` + +Essas configurações podem estar persistentes na configuração do seu [projeto](../reference/project-config). + +## Como funciona + +Em uma compilação padrão, todos os métodos vinculados estão disponíveis no frontend sob a variável `window.go`. Quando esses métodos são chamados, o método backend correspondente é chamado usando o nome da função totalmente qualificada. Quando usando uma compilação ofuscada, os métodos são vinculados usando um ID em vez de um nome. Os bindings gerados no diretório `wailsjs` usam esses IDs para chamar as funções de backend. + +:::note + +Para garantir que o seu aplicativo irá funcionar no modo ofuscado, você deve usar os bindings geradas sob o diretório `wailsjs` no seu aplicativo. + +::: + +## Exemplo + +Importing the "Greet" method from the bindings like this: + +```js +import { Greet } from "../../wailsjs/go/main/App"; + +// snip +Greet("World"); +``` + +irá garantir que o método funcionará corretamente no modo ofuscado, como os bindings serão regenerados com IDs e o mecanismo de chamada atualizado. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx new file mode 100644 index 00000000000..dcd13f147c3 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx @@ -0,0 +1,10 @@ +# Rolar demais + +[Overscroll](https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior) é o "efeito de salto" que você às vezes obtém quando você rola além dos limites de conteúdo de uma página. This is common in mobile apps. Isso pode ser desativado usando CSS: + +```css +html { + height: 100%; + overflow: hidden; +} +``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx new file mode 100644 index 00000000000..550e73a57f4 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx @@ -0,0 +1,47 @@ +# Roteamento + +O roteamento é uma maneira popular de alternar as telas de um aplicativo. Esta página oferece algumas orientações sobre como fazer isso. + +## Vue + +A abordagem recomendada para roteamento em Vue é o [Hash Mode](https://next.router.vuejs.org/guide/essentials/history-mode.html#hash-mode): + +```js +import { createRouter, createWebHashHistory } from "vue-router"; + +const router = createRouter({ + history: createWebHashHistory(), + routes: [ + //... + ], +}); +``` + +## Angular + +A abordagem recomendada para roteamento em Angular é [HashLocationStrategy](https://codecraft.tv/courses/angular/routing/routing-strategies#_hashlocationstrategy): + +```ts +RouterModule.forRoot(routes, { useHash: true }); +``` + +## React + +A abordagem recomendada para roteamento em React é [HashRouter](https://reactrouter.com/en/main/router-components/hash-router): + +```jsx +import { HashRouter } from "react-router-dom"; + +ReactDOM.render( + + {/* The rest of your app goes here */} + + } exact /> + } /> + } /> + {/* more... */} + + , + root +); +``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx new file mode 100644 index 00000000000..c3e0c269658 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx @@ -0,0 +1,387 @@ +# Assinatura de Código + +Este é um guia sobre como você pode assinar seus binários gerados com Wails no MacOS e Windows. O guia visará ambientes de CI, mais especificamente as GitHub Actions. + +## Windows + +Primeiro você precisa de um certificado de assinatura de código. Se você ainda não tiver uma, a página de informações da Microsoft lista alguns provedores [aqui](https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/get-a-code-signing-certificate). Observe que um certificado EV não é necessário a menos que você precise escrever um software no nível kernel como drivers de dispositivos. Para assinar o seu aplicativo Wails, um certificado de assinatura de código padrão vai dar certo. + +Pode ser uma boa ideia verificar com seu provedor de certificados como assinar seus binários na sua máquina local antes de direcionar sistemas de compilação automatizada. só para que você saiba se há exigências especiais. Por exemplo, [aqui](https://www.ssl.com/how-to/using-your-code-signing-certificate/) é o guia de assinatura de código de SSL.com para Windows. Se você sabe como assinar localmente, será mais fácil solucionar quaisquer possíveis problemas em um ambiente de CI. Por exemplo, os certificados de assinatura de código SSL.com exigem a flag `/tr` para [SignTool.exe](https://docs.microsoft.com/en-us/windows/win32/seccrypto/signtool) enquanto outros provedores só precisam da flag `/t` para fornecer o servidor de marcação de tempo. GitHub Actions populares para assinar binários Windows como [este](https://github.com/Dana-Prajea/code-sign-action) não suporta a flag `/tr` no SignTool.exe. Portanto, este guia focará em assinar nosso aplicativo manualmente com comandos do PowerShell, mas você pode usar ações como a ação de [de co-sign-action](https://github.com/Dana-Prajea/code-sign-action) se preferir. + +Em primeiro lugar, vamos nos certificar de que somos capazes de construir nosso aplicativo Wails no nosso GitHub CI. Aqui está um pequeno modelo de fluxo de trabalho: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend manually here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +Em seguida, precisamos dar ao fluxo de trabalho do GitHub acesso ao nosso certificado de assinatura. Isso é feito codificando seu certificado .pfx ou .p12 em uma string base64. Para fazer isso em PowerShell, use o seguinte comando assumindo que seu certificado se chama 'my-cert.p12': + +```PowerShell +certutil -encode .\my-cert.p12 my-cert-base64.txt +``` + +Você deve ter seu arquivo .txt com o certificado codificado em base64. Deve começar com _-----BEGIN CERTIFICATE-----_ e terminar com _-----END CERTIFICATE-----_. Agora você precisa criar duas ações secretas no GitHub. Navegue até _Configurações -> Segredos -> Ações_ e crie os dois seguintes segredos: + +- **WIN_SIGNING_CERT** com o conteúdo de seu texto codificado no certificado base64. +- **WIN_SIGNING_CERT_PASSWORD** com o conteúdo da sua senha do certificado. + +Agora estamos prontos para implementar a assinatura em nosso fluxo de trabalho usando um dos dois métodos: + +### Método 1: Assinar com comandos + +Esse método usa comandos PowerShell para assinar nosso aplicativo, e deixa o controle de todo o processo de assinatura. + +Após o passo `Build Wails app`, podemos adicionar o seguinte passo ao nosso fluxo de trabalho: + +```yaml +- name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd /t /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' + +``` + +Este script cria um novo diretório para o seu arquivo de certificado, cria o arquivo de certificado do nosso segredo base64, converte-o em um arquivo .pfx, e finalmente assina o binário. As seguintes variáveis precisam ser substituídas na última linha: + +- **signing algorithm**: geralmente sha256. +- **timestamping server**: URL para o servidor de timestamping a ser usado com seu certificado. +- **path to binary**: caminho para o binário que você deseja assinar. + +Dado que nossa configuração Wails tem `outputfilename` definido para "app.exe" e que temos um certificado de SSL.com, este é o nosso fluxo de trabalho: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\app.exe + + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +### Método 2: assinar automaticamente com Action + +É possível usar um código Windows assinando uma ação como [este](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate) um, mas nota que requer um hash SHA1 para o certificado e um nome de certificado. Veja um exemplo de como configurá-lo na [loja da ações](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate). + +--- + +## MacOS + +Primeiro você precisa do seu certificado de assinatura de código da Apple. Se você não tem uma, uma pesquisa simples do Google irá ajudá-lo a adquirir uma. Depois de ter o certificado, você precisa exportá-lo e codificá-lo para base64. [Este tutorial](https://localazy.com/blog/how-to-automatically-sign-macos-apps-using-github-actions) te mostra como fazer isso de uma maneira fácil. Depois de ter exportado seu arquivo de certificado .p12, você pode codificá-lo para base64, como visto no tutorial com o seguinte comando: + +```bash +base64 Certificates.p12 | pbcopy +``` + +Agora você está pronto para criar alguns segredos de projeto do GitHub, assim como no Windows: + +- **APPLE_DEVELOPER_CERTIFICATE_P12_BASE64** com o conteúdo de seu certificado base64 recém-copiado. +- **APPLE_DEVELOPER_CERTIFICATE_PASSWORD** com o conteúdo da senha do seu certificado. +- **APPLE_PASSWORD** com o conteúdo de uma senha específica para sua conta Apple-ID que pode gerar [aqui](https://appleid.apple.com/account/manage). + +Vamos nos certificar de que somos capazes de construir nosso aplicativo Wails em nosso fluxo de trabalho do GitHub. Aqui está um pequeno modelo: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +Para assinar o código no macOS, [gon](https://github.com/mitchellh/gon) é uma ferramenta muito útil para a assinatura do código e a comunicação com os servidores Apple, também escrito em Go, e será usado neste guia. + +Após o passo `Build Wails app`, adicione o seguinte ao fluxo de trabalho: + +```yaml +- name: MacOS download gon for code signing and app notarization + if: matrix.platform == 'macos-latest' + run: | + brew install mitchellh/gon/gon +``` + +Agora precisamos configurar alguns arquivos de configuração do gon no nosso diretório `build/darwin`: + +1. gon-sign.json: + +```json +{ + "source": ["./build/bin/app.app"], + "bundle_id": "app.myapp", + "apple_id": { + "username": "my-appleid@email.com", + "password": "@env:APPLE_PASSWORD" + }, + "sign": { + "application_identity": "Developer ID Application: My Name" + } +} +``` + +Onde o `source` é o binário do seu Wails, `bundle_id` é o seu ID do pacote, `apple_id` contém o seu nome de usuário do ID Apple e a senha do aplicativo que você criou antes, e `sign.application_identity` é sua identidade que você pode encontrar executando o seguinte comando: + +```bash +security find-identity -v -p codesigning +``` + +2. entitlements.plist: + +```plist + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + + +``` + +Neste arquivo, você configura os direitos que você precisa para seu aplicativo, por exemplo, permissões de câmera se seu app usa a câmera. Leia mais sobre entitlements [aqui](https://developer.apple.com/documentation/bundleresources/entitlements). + +Verifique se você atualizou seu arquivo `Info.plist` com o mesmo pacote de ID que você digitou em `gon-sign.json`. Aqui está um arquivo `Info.plis` de exemplo: + +```plist + + + CFBundlePackageTypeAPPL + CFBundleNameMyApp + CFBundleExecutableapp + CFBundleIdentifierapp.myapp + CFBundleVersion0.1.0 + CFBundleGetInfoStringMy app is cool and nice and chill and + CFBundleShortVersionString0.1.0 + CFBundleIconFileiconfile + LSMinimumSystemVersion10.13.0 + NSHighResolutionCapabletrue + LSApplicationCategoryTypepublic.app-category.utilities + NSHumanReadableCopyright© Me + +``` + +Agora estamos prontos para adicionar a etapa de assinatura em nosso fluxo de trabalho após a construção do aplicativo Wails: + +```yaml +- name: Import Code-Signing Certificates for macOS + if: matrix.platform == 'macos-latest' + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} +- name: Sign our macOS binary + if: matrix.platform == 'macos-latest' + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json +``` + +Por favor, note que a assinatura de binários com Apple pode levar a de minutos a horas. + +## Arquivo de fluxo combinado: + +Aqui está nosso arquivo de fluxo de trabalho do GitHub com Windows + macOS combinados: + +```yaml +name: "example combined" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: MacOS download gon for code signing and app notarization + if: matrix.platform == 'macos-latest' + run: | + brew install mitchellh/gon/gon + - name: Import Code-Signing Certificates for macOS + if: matrix.platform == 'macos-latest' + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} + - name: Sign our macOS binary + if: matrix.platform == 'macos-latest' + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json + - name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\Monitor.exe + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +# Notas finais + +Este guia inspirado no projeto RiftShare e seu fluxo de trabalho, o que é altamente recomendado para verificar [aqui](https://github.com/achhabra2/riftshare/blob/main/.github/workflows/build.yaml). diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx new file mode 100644 index 00000000000..dc7706f8ffa --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx @@ -0,0 +1,81 @@ +# Single Instance Lock + +Single instance lock is a mechanism that allows you to prevent multiple instances of your app from running at the same time. +It is useful for apps that are designed to open files from the command line or from the OS file explorer. + +## Important + +Single Instance Lock does not implement a secure communications protocol between instances. When using single instance lock, +your app should treat any data passed to it from second instance callback as untrusted. +You should verify that args that you receive are valid and don't contain any malicious data. + +## How it works + +Windows: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via a shared window using [SendMessage](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage) +macOS: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via [NSDistributedNotificationCenter](https://developer.apple.com/documentation/foundation/nsdistributednotificationcenter) +Linux: Single instance lock is implemented using [dbus](https://www.freedesktop.org/wiki/Software/dbus/). The dbus name is generated from the unique id that you provide. Data is passed to the first instance via [dbus](https://www.freedesktop.org/wiki/Software/dbus/) + +## Usage + +When creating your app, you can enable single instance lock by passing a `SingleInstanceLock` struct to the `App` struct. +Use the `UniqueId` field to specify a unique id for your app. +This id is used to generate the mutex name on Windows and macOS and the dbus name on Linux. Use a UUID to ensure that the id is unique. +The `OnSecondInstanceLaunch` field is used to specify a callback that is called when a second instance of your app is launched. +The callback receives a `SecondInstanceData` struct that contains the command line arguments passed to the second instance and the working directory of the second instance. + +Note that OnSecondInstanceLaunch don't trigger windows focus. +You need to call `runtime.WindowUnminimise` and `runtime.Show` to bring your app to the front. +Note that on linux systems window managers may prevent your app from being brought to the front to avoid stealing focus. + +```go title="main.go" +var wailsContext *context.Context + +// NewApp creates a new App application struct +func NewApp() *App { + return &App{} +} + +// startup is called when the app starts. The context is saved +// so we can call the runtime methods +func (a *App) startup(ctx context.Context) { + wailsContext = &ctx +} + +func (a *App) onSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) { + secondInstanceArgs = secondInstanceData.Args + + println("user opened second instance", strings.Join(secondInstanceData.Args, ",")) + println("user opened second from", secondInstanceData.WorkingDirectory) + runtime.WindowUnminimise(*wailsContext) + runtime.Show(*wailsContext) + go runtime.EventsEmit(*wailsContext, "launchArgs", secondInstanceArgs) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + OnStartup: app.startup, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx new file mode 100644 index 00000000000..8281281f325 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx @@ -0,0 +1,153 @@ +# SvelteKit + +Este guia será para: + +1. Passos de instalação do Miminal - Os passos necessários para obter uma instalação mínima de Wails funcionando para o SvelteKit. +2. Script de Instalação - Bash script para cumprir os passos de Instalação Mínima com a marca opcional de Wails. +3. Notas importantes - Problemas que podem ser encontrados ao usar o SvelteKit + Wails e correções. + +## 1. Passos mínimos de instalação + +##### Instalar Wails para Svelte. + +- `wails init -n myapp -t svelte` + +##### Exclua o front-end do Svelte. + +- Navegue até a pasta myapp recém-criada. +- Excluir a pasta chamada "frontend" + +##### Enquanto estiver na raiz do projeto Wails. Use o seu gerenciador de pacotes favorito e instale o SvelteKit como o novo frontend. Siga as instruções. + +- `npm create svelte@latest frontend` + +##### Modificar o wails.json. + +- Add `"wailsjsdir": "./frontend/src/lib",` Observe que é aqui que suas funções Go e runtime aparecerão. +- Mude o frontend do seu gerenciador de pacotes se não estiver usando npm. + +##### Modificar o main.go. + +- O primeiro comentário `//go:embed all:frontend/dist` precisa ser alterado para `//go:embed all:frontend/build` + +##### Instalar/remover dependências usando seu gerenciador de pacote favorito. + +- Entre na sua pasta "frontend". +- `npm i` +- `npm uninstall @sveltejs/adapter-auto` +- `npm i -D @sveltejs/adapter-static` + +##### Alterar adaptador em svelte.config.js + +- A primeira linha de arquivo altera `import adapter from '@sveltejs/adapter-auto';` to `import adapter from '@sveltejs/adapter-static';` + +##### Coloque o SvelteKit no modo SPA com pré-renderização. + +- Crie um arquivo sob myapp/frontend/src/routes/ chamado +layout.ts/+layout.js. +- Adicione duas linhas ao recém-criado arquivo `export const prerender = true` e `export const ssr = false` + +##### Testar instalação. + +- Navegue de volta à raiz do projeto Wails (um diretório para cima). +- execute `wails dev` +- Se a aplicação não executar, por favor verifique os passos anteriores. + +## 2. Script de Instalação + +##### Este Script do Bash faz as etapas listadas acima. Certifique-se de ler o script e de entender o que o script está fazendo no seu computador. + +- Criar um arquivo sveltekit-wails.sh +- Copie o código abaixo para o novo arquivo e o salve. +- Torná-lo executável com `chmod +x sveltekit-wails.sh` +- A marca é um parâmetro opcional abaixo que adiciona de volta na marca de fregueses. Deixe o terceiro parâmetro em branco para não inserir a marca das Wails. +- Exemplo de uso: `./sveltekit-wails.sh pnpm newapp brand` + +##### sveltekit-wails.sh: + +``` +manager=$1 +project=$2 +brand=$3 +wails init -n $project -t svelte +cd $project +sed -i "s|npm|$manager|g" wails.json +sed -i 's|"auto",|"auto",\n "wailsjsdir": "./frontend/src/lib",|' wails.json +sed -i "s|all:frontend/dist|all:frontend/build|" main.go +if [[ -n $brand ]]; then + mv frontend/src/App.svelte +page.svelte + sed -i "s|'./assets|'\$lib/assets|" +page.svelte + sed -i "s|'../wails|'\$lib/wails|" +page.svelte + mv frontend/src/assets . +fi +rm -r frontend +$manager create svelte@latest frontend +if [[ -n $brand ]]; then + mv +page.svelte frontend/src/routes/+page.svelte + mkdir frontend/src/lib + mv assets frontend/src/lib/ +fi +cd frontend +$manager i +$manager uninstall @sveltejs/adapter-auto +$manager i -D @sveltejs/adapter-static +echo -e "export const prerender = true\nexport const ssr = false" > src/routes/+layout.ts +sed -i "s|-auto';|-static';|" svelte.config.js +cd .. +wails dev +``` + +## 3. Notas importantes + +##### Os arquivos do servidor causarão falhas de construção. + +- \+layout.server.ts, +page.server.ts, +server.ts ou qualquer arquivo com "server" em nome falhará na construção enquanto todas as rotas forem pré-renderizadas. + +##### O tempo de execução do Wails descarrega com navegações de página inteira! + +- Tudo que causa navegações de página completa: `window.location.href = '//'` ou recarga do menu de contexto ao usar wails dev. Isso significa que você pode acabar perdendo a capacidade de chamar qualquer falha no aplicativo em tempo de execução. Há duas formas de trabalhar em torno desta questão. +- Use `import { goto } from '$app/navigation'` e então chame `goto('//')` em sua + page.svelte. Isso impedirá uma navegação de página completa. +- Se a navegação por página inteira não puder ser impedido que o tempo de execução do Wails seja adicionado a todas as páginas, adicionando o abaixo ao `` de myapp/frontend/src/app. Mt + +``` + +... + + + +... + +``` + +Veja https://wails.io/docs/guides/frontend para mais informações. + +##### Os dados de e-mail podem ser carregados e atualizados a partir de +page.ts/+page.js para +page.svelte. + +- \+page.ts/+page.js funciona bem com o load() https://kit.svelte.dev/docs/load#page-data +- invalidateAll() em +page.svelte irá chamar load() de +page.ts/+page.js https://kit.svelte.dev/docs/load#rerunning-load-functions-manual-invalidation. + +##### Tratamento de erros + +- Erros esperados usando o erro Throw funcionam em +page.ts/+page.js com uma página +error.svelte. https://kit.svelte.dev/docs/errors#expected-errors +- Erros inesperados farão com que o aplicativo se torne inutilizável. Somente a opção de recuperação (conhecida até agora) de erros inesperados é recarregar o aplicativo. Para fazer isso, crie um arquivo myapp/frontend/src/hooks.client.ts e adicione o código abaixo ao arquivo. + +``` +import { WindowReloadApp } from '$lib/wailsjs/runtime/runtime' +export async function handleError() { + WindowReloadApp() +} +``` + +##### Usando formas e funções de manipulação + +- A maneira mais simples é chamar uma função do formulário é o padrão, vincular:valor suas variáveis e evitar submissão `` +- A maneira mais avançada é use:enhance (aprimoramento progressivo) que permitirá acesso conveniente a formData, formElemento, emissor. A nota importante é sempre cancel() o formulário que impede o comportamento do lado do servidor. https://kit.svelte.dev/docs/form-actions#progressive-enhancement Exemplo: + +``` + { + cancel() + console.log(Object.fromEntries(formData)) + console.log(formElement) + console.log(submitter) + handle() +}}> +``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx new file mode 100644 index 00000000000..2ae61796b73 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx @@ -0,0 +1,97 @@ +# Templates + +Wails gera projetos a partir de modelos pré-criados. Na v1, este era um conjunto de projetos que estavam sujeitos a sair de moda. No v2, para capacitar a comunidade, alguns novos recursos foram adicionados para os templates: + +- Capacidade de gerar projetos a partir de [Modelos Remotos](../reference/cli.mdx#remote-templates) +- Ferramentas para ajudar a criar seus próprios modelos + +## Criando Templates + +Para criar um template, você pode usar o comando `wails generate template`. Para gerar um modelo padrão, execute: + +`wails generate template -name mytemplate` + +Isso cria o diretório "mytemplate" com os arquivos padrão: + +```shell title=mytemplate/ +. +|-- NEXTSTEPS.md +|-- README.md +|-- app.tmpl.go +|-- frontend +| `-- dist +| |-- assets +| | |-- fonts +| | | |-- OFL.txt +| | | `-- nunito-v16-latin-regular.woff2 +| | `-- images +| | `-- logo-dark.svg +| |-- index.html +| |-- main.css +| `-- main.js +|-- go.mod.tmpl +|-- main.tmpl.go +|-- template.json +`-- wails.tmpl.json +``` + +### Visão Geral do Modelo + +O modelo padrão consiste nos seguintes arquivos e diretórios: + +| Nome do arquivo / diretório | Descrição | +| --------------------------- | -------------------------------------------- | +| NEXTSTEPS.md | Instruções sobre como completar o modelo | +| README.md | O README publicado com o modelo | +| app.tmpl.go | Arquivo de modelo `app.go` | +| frontend/ | O diretório que contém os assets do frontend | +| go.mod.tmpl | Arquivo de modelo `go.mod` | +| main.tmpl.go | Arquivo de modelo `main.go` | +| template.json | Os metadados do modelo | +| wails.tmpl.json | Arquivo de modelo `wails.json` | + +Neste ponto é aconselhável seguir os passos em `NEXTSTEPS.md`. + +## Criando um Template de um Projeto Existente + +É possível criar um modelo a partir de um projeto de frontend existente, passando o caminho para o projeto ao gerar o template. Vamos agora andar sobre como criar um modelo do Vue 3: + +- Instale o vue cli: `npm install -g @vue/cli` +- Crie o projeto padrão: `vue create vue3-base` + - Selecione `Padrão (Vue 3) ([Vue 3] babel, eslint)` +- Depois que o projeto for gerado, execute: + +```shell +> wails generate template -name wails-vue3-template -frontend .\vue3-base\ +Extracting base template files... +Migrating existing project files to frontend directory... +Updating package.json data... +Renaming package.json -> package.tmpl.json... +Updating package-lock.json data... +Renaming package-lock.json -> package-lock.tmpl.json... +``` + +- O template agora pode ser personalizado conforme especificado no arquivo `NEXTSTEPS.md` +- Uma vez que os arquivos estão prontos, eles podem ser testados executando: `wails init -n my-vue3-project -t .\wails-vue3-template\` +- Para testar o novo projeto, execute: `cd meu-vue3-projeto` e `wails constroem` +- Uma vez que o projeto tenha compilado, execute-o: `.\build\bin\my-vue3-project.exe` +- Você deve ter um aplicativo Vue3 que funcione plenamente: + +```mdx-code-block +
+ +
+``` + +## Publicando Templates + +A publicação de um template está simplesmente enviando os arquivos para o GitHub. São encorajadas as seguintes melhores práticas: + +- Remova todos os arquivos e diretórios indesejados (como `.git`) do seu diretório no frontend +- Certifique-se de que `template.json` esteja completo, especialmente `helpurl` +- Faça push dos arquivos para o GitHub +- Crie um PR na página [Templates de Comunidade](../community/templates.mdx) +- Anuncie o modelo no fórum de discussão [de Anúncio de Modelo](https://github.com/wailsapp/wails/discussions/825) diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx new file mode 100644 index 00000000000..b4980716836 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx @@ -0,0 +1,368 @@ +# Resolução de Problemas + +Uma variedade de dicas de solução de problemas. + +## O comando `wail` parece estar faltando? + +Se o sistema está relatando que o comando `wails` está faltando, verifique se você seguiu o guia de instalação do Go corretamente. Normalmente, isso significa que o diretório `go/bin` no diretório inicial do seu usuário não está na variável `PATH` ambiente. Você normalmente também precisará fechar e reabrir qualquer prompt de comando aberto para que as alterações no ambiente feitas pelo instalador sejam refletidas no prompt de comando. + +## Meu aplicativo está exibindo uma tela branca/em branco + +Verifique se sua aplicação inclui os conteúdos do diretório correto. No seu arquivo `main.go`, você terá algo semelhante ao seguinte código: + +```go +//go:embed all:frontend/dist +var assets embed.FS +``` + +Verifique que `frontend/dist` contém os ativos da aplicação. + +### Mac + +Se isso acontecer no Mac, tente adicionar o seguinte ao seu `Info.plist`: + +```xml +NSAppTransportSecurity + + NSAllowsLocalNetworking + + +``` + +Reference: https://github.com/wailsapp/wails/issues/1504#issuecomment-1174317433 + +## Aplicativo Mac inválido + +Se a sua aplicação construída se parece com isso no buscador: + +```mdx-code-block +

+ +

+``` + +é provável que o `info.plist` do seu aplicativo seja inválido. Atualize o arquivo em `build/.app/Contents/info.plist` e verifique se os dados são válidos, verifique se o nome binário está correto. Para persistir nas alterações, copie o arquivo de volta para o diretório `build/darwin`. + +## Meu aplicativo não está exibindo o ícone correto no Windows Explorer + +Se seu aplicativo não estiver exibindo o ícone correto, tente excluir o arquivo `IconCache.db` oculto localizado na pasta Diretório `C:\Users\<seu nome de usuário>\AppData\Local`. Isto irá forçar o Windows a reconstruir o cache de ícones. + +Reference: https://github.com/wailsapp/wails/issues/2360#issuecomment-1556070036 + +## Não é possível chamar o método backend no frontend com argumentos variados + +Se você tem um método de backend definido com parâmetros variadicos, por exemplo: + +```go +func (a *App) TestFunc(msg string, args ...interface{}) error { + // Code +} +``` + +chamar esse método a partir do frontend como isso irá falhar: + +```js +var msg = "Hello: "; +var args = ["Go", "JS"]; +window.go.main.App.TestFunc(msg, ...args) + .then((result) => { + //do things here + }) + .catch((error) => { + //handle error + }); +``` + +Gambiarra: + +```js +var msg = "Hello "; +var args = ["Go", "JS"]; +window.go.main.App.TestFunc(msg, args) + .then((result) => { + //without the 3 dots + //do things here + }) + .catch((error) => { + //handle error + }); +``` + +Credit: https://github.com/wailsapp/wails/issues/1186 + +## Estou recebendo erros de proxy ao tentar instalar o Wails + +Se você estiver recebendo erros como este: + +``` +"https://proxy.golang.org/github.com/wailsapp/wails/cmd/wails/@v/list": dial tcp 172.217.163.49:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. +``` + +é provavelmente porque o Proxy oficial Go está sendo bloqueado (usuários na China relataram isto). A solução é configurar o proxy manualmente, por exemplo: + +``` +go env -w GO111MODULE=on +go env -w GOPROXY=https://goproxy.cn,direct +``` + +Reference: https://github.com/wailsapp/wails/issues/1233 + +## O TypeScript gerado não tem os tipos corretos + +Às vezes, o TypeScript gerado não tem os tipos corretos. Para mitigar isso, é possível especificar quais tipos devem ser gerados usando a tag de struct `ts_type`. Para mais detalhes do, leia [isto](https://github.com/tkrajina/typescriptify-golang-structs#custom-types). + +## Quando navego longe do `index.html`, não consigo chamar métodos no frontend + +Se você navegar do `index.html` para um novo arquivo html, o contexto será perdido. Isso pode ser corrigido adicionando as seguintes importações para a seção `` de qualquer nova página que você navegar: + +```html + + + + +``` + +Reference: https://github.com/wailsapp/wails/discussions/1512 + +## Eu recebo `muitos arquivos abertos` erros no meu Mac quando eu rodo `wails` + +Por padrão, o macOS só permitirá que você abra um máximo de 256 arquivos. Isso pode afetar o comando `wails dev`. Este limite pode ser aumentado em execução: `ulimit -n 1024` no terminal. + +FSNotify é [procurando mudar para os fsevents](https://github.com/fsnotify/fsnotify/issues/11) da Apple para Mac. Se isso não estiver concluído em breve, criaremos nossa própria implementação, monitorada [aqui](https://github.com/wailsapp/wails/issues/1733). + +## Meu aplicativo para Mac me dá erros estranhos de compilação + +Alguns usuários relataram ver erros de compilação como os seguintes: + +```shell +# github.com/wailsapp/wails/v2/internal/frontend/desktop/darwin +In file included from ../../pkg/mod/github.com/wailsapp/wails/v2@v2.0.0-beta.44.2/internal/frontend/desktop/darwin/callbacks.go:9: +In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:12: +/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSBundle.h:91:143: error: function does not return NSString +- (NSAttributedString *)localizedAttributedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName NS_FORMAT_ARGUMENT(1) NS_REFINED_FOR_SWIFT API_AVAILABLE(macos(12.0), ios(15.0), watchos(8.0), tvos(15.0)); + ~~~~~~~~~~~~~~ ^ ~ +/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:103:48: note: expanded from macro 'NS_FORMAT_ARGUMENT' + #define NS_FORMAT_ARGUMENT(A) __attribute__ ((format_arg(A))) +``` + +Isto é _normalmente_ devido a uma incompatibilidade com a versão do sistema operacional que você está executando e a versão das Ferramentas de Comando XCode instalada. Se você vir um erro como este, tente atualizar suas Ferramentas de Linha de Comando XCode para a versão mais recente. + +Se reinstalar as Ferramentas de Comando Xcode ainda falhar, você pode verificar o caminho onde o kit de ferramentas está usando: + +`xcode-select -p` + +Se `/Applications/Xcode.app/Contents/Developer` for exibido, rode `sudo xcode-select --switch /Library/Developer/CommandLineTools` + +Fontes: https://github.com/wailsapp/wails/issues/1806 and https://github.com/wailsapp/wails/issues/1140#issuecomment-1290446496 + +## My application won't compile on Mac + +Se você estiver recebendo erros como este: + +```shell +l1@m2 GoEasyDesigner % go build -tags dev -gcflags "all=-N -l" +/Users/l1/sdk/go1.20.5/pkg/tool/darwin_arm64/link: running clang failed: exit status 1 +Undefined symbols for architecture arm64: + "_OBJC_CLASS_$_UTType", referenced from: + objc-class-ref in 000016.o +ld: symbol(s) not found for architecture arm64 +clang: error: linker command failed with exit code 1 (use -v to see invocation) +``` +Ensure you have the latest SDK installed. If so and you're still experiencing this issue, try the following: + +```shell +export CGO_LDFLAGS="-framework UniformTypeIdentifiers" && go build -tags dev -gcflags "all=-N -l" +``` + +Sources: https://github.com/wailsapp/wails/pull/2925#issuecomment-1726828562 + + +-- + +## Não foi possível iniciar o serviço: A versão do host "x.x.x não coincide com a versão binária "x.x.x" + +É preferível adicionar `frontend/node_modules` e `frontend/package-lock.json` ao seu `.gitignore`. Caso contrário, ao abrir o repositório em outra máquina que pode ter diferentes versões do Node instaladas, talvez você não seja capaz de executar seu aplicativo. + +Se isso acontecer, simplesmente exclua `frontend/node_modules` e `frontend/pacote-lock. soa` e corra os seus wails `constroem` ou `wails dev` comando. + +## Processo de compilação travado em "Gerando vinculações" + +Processo de geração de Bindings executa sua aplicação em um modo especial. Se o aplicativo, intencionalmente ou não intencionalmente, contém um laço infinito (ou seja, não sair após `wails.Run()` terminado), isto pode levar a construção do processo travado na geração do palco de amarras. Por favor, certifique-se de que seu código sai corretamente. + +## Aplicação Mac pisca branco na inicialização + +Isto é devido ao plano de fundo padrão do webview ser branco. Se você quiser usar a cor de fundo da janela, você pode tornar o plano de fundo do webview transparente usando a seguinte configuração: + +```go + err := wails.Run(&options.App{ + Title: "macflash", + Width: 1024, + Height: 768, + // Other settings + Mac: &mac.Options{ + WebviewIsTransparent: true, + }, + }) +``` + +## I get a "Microsoft Edge can't read or write to its data directory" error when running my program as admin on Windows + +You set your program to require admin permissions and it worked great! Unfortunately, some users are seeing a "Microsoft Edge can't read or write to its data directory" error when running it. + +When a Windows machine has two local accounts: + +- Alice, an admin +- Bob, a regular user + +Bob sees a UAC prompt when running your program. Bob enters Alice's admin credentials into this prompt. The app launches with admin permissions under Alice's account. + +Wails instructs WebView2 to store user data at the specified `WebviewUserDataPath`. It defaults to `%APPDATA%\[BinaryName.exe]`. + +Because the application is running under Alice's account, `%APPDATA%\[BinaryName.exe]` resolves to `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`. + +WebView2 [creates some child processes under Bob's logged-in account instead of Alice's admin account](https://github.com/MicrosoftEdge/WebView2Feedback/issues/932#issue-807464179). Since Bob cannot access `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`, the "Microsoft Edge can't read or write to its data directory" error is shown. + +Possible solution #1: + +Refactor your application to work without constant admin permissions. If you just need to perform a small set of admin tasks (such as running an updater), you can run your application with the minimum permissions and then use the `runas` command to run these tasks with admin permissions as needed: + +```go +//go:build windows + +package sample + +import ( + "golang.org/x/sys/windows" + "syscall" +) + +// Calling RunAs("C:\path\to\my\updater.exe") shows Bob a UAC prompt. Bob enters Alice's admin credentials. The updater launches with admin permissions under Alice's account. +func RunAs(path string) error { + verbPtr, _ := syscall.UTF16PtrFromString("runas") + exePtr, _ := syscall.UTF16PtrFromString(path) + cwdPtr, _ := syscall.UTF16PtrFromString("") + argPtr, _ := syscall.UTF16PtrFromString("") + + var showCmd int32 = 1 //SW_NORMAL + + err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd) + if err != nil { + return err + } + return nil +} +``` + +Possible solution #2: + +Run your application with extended permissions. If you absolutely must run with constant admin permissions, WebView2 will function correctly if you use a data directory accessible by both users and you also launch your app with the `SeBackupPrivilege`, `SeDebugPrivilege`, and `SeRestorePrivilege` permissions. Here's an example: + +```go +package main + +import ( + "embed" + "os" + "runtime" + + "github.com/fourcorelabs/wintoken" + "github.com/hectane/go-acl" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +//go:embed all:frontend/dist +var assets embed.FS + +const ( + fixedTokenKey = "SAMPLE_RANDOM_KEY" + fixedTokenVal = "with-fixed-token" + webviewDir = "C:\\ProgramData\\Sample" +) + +func runWithFixedToken() { + println("Re-launching self") + token, err := wintoken.OpenProcessToken(0, wintoken.TokenPrimary) //pass 0 for own process + if err != nil { + panic(err) + } + defer token.Close() + + token.EnableTokenPrivileges([]string{ + "SeBackupPrivilege", + "SeDebugPrivilege", + "SeRestorePrivilege", + }) + + cmd := exec.Command(os.Args[0]) + cmd.Args = os.Args + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", fixedTokenKey, fixedTokenVal)) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.SysProcAttr = &syscall.SysProcAttr{Token: syscall.Token(token.Token())} + if err := cmd.Run(); err != nil { + println("Error after launching self:", err) + os.Exit(1) + } + println("Clean self launch :)") + os.Exit(0) +} + +func main() { + if runtime.GOOS == "windows" && os.Getenv(fixedTokenKey) != fixedTokenVal { + runWithFixedToken() + } + + println("Setting data dir to", webviewDir) + if err := os.MkdirAll(webviewDir, os.ModePerm); err != nil { + println("Failed creating dir:", err) + } + if err := acl.Chmod(webviewDir, 0777); err != nil { + println("Failed setting ACL on dir:", err) + } + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "sample-data-dir", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + Windows: &windows.Options{ + WebviewUserDataPath: webviewDir, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +If you use a data directory accessible by both users but not the extended privileges, you will receive a WebView2 `80010108 The object invoked has disconnected from its clients` error. + +Possible future solution #3: [run WebView2 using an in-memory mode if implemented](https://github.com/MicrosoftEdge/WebView2Feedback/issues/3637#issuecomment-1728300982). + +## WebView2 installation succeeded, but the wails doctor command shows that it is not installed + +If you have installed WebView2, but the `wails doctor` command shows that it is not installed, it is likely that the WebView2 runtime installed was for a different architecture. You can download the correct runtime from [here](https://developer.microsoft.com/en-us/microsoft-edge/webview2/). + +Source: https://github.com/wailsapp/wails/issues/2917 + +## WebVie2wProcess failed with kind + +If your Windows app generates this kind of error, you can check out what the error means [here](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2processfailedkind?view=webview2-winrt-1.0.2045.28). + diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx new file mode 100644 index 00000000000..03962a2184c --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx @@ -0,0 +1,82 @@ + +# Visual Studio Code + +Esta página é para dicas e truques diversos ao usar o Visual Studio Code com Wails. + +## Configuração do Vetur + +Muito obrigado [@Lyimmi](https://github.com/Lyimmi) por esta dica. Originalmente publicada [aqui](https://github.com/wailsapp/wails/issues/1791#issuecomment-1228158349). + +Vetur é um popular plugin para o Visual Studio Code que fornece realce de sintaxe e conclusão de código para projetos Vue. Ao carregar um projeto Wails no VSCode, Vetur lançará um erro já que está esperando para encontrar o projeto frontend no diretório raiz. Para consertar isso, você pode fazer o seguinte: + +Crie um arquivo chamado `vetur.config.js` na raiz do projeto. + +```javascript +// vetur.config.js +/** @type {import('vls').VeturConfig} */ +module.exports = { + // **optional** default: `{}` + // override vscode settings + // Notice: It only affects the settings used by Vetur. + settings: { + "vetur.useWorkspaceDependencies": true, + "vetur.experimental.templateInterpolationService": true + }, + // **optional** default: `[{ root: './' }]` + // support monorepos + projects: [ + { + // **required** + // Where is your project? + // It is relative to `vetur.config.js`. + // root: './packages/repo1', + root: './frontend', + // **optional** default: `'package.json'` + // Where is `package.json` in the project? + // We use it to determine the version of vue. + // It is relative to root property. + package: './package.json', + // **optional** + // Where is TypeScript config file in the project? + // It is relative to root property. + tsconfig: './tsconfig.json', + // **optional** default: `'./.vscode/vetur/snippets'` + // Where is vetur custom snippets folders? + snippetFolder: './.vscode/vetur/snippets', + // **optional** default: `[]` + // Register globally Vue component glob. + // If you set it, you can get completion by that components. + // It is relative to root property. + // Notice: It won't actually do it. You need to use `require.context` or `Vue.component` + globalComponents: [ + './src/components/**/*.vue' + ] + } + ] +} +``` + +Agora, configure `frontend/tsconfig.json`: + +```javascript +{ + "compilerOptions": { + "module": "system", + "noImplicitAny": true, + "removeComments": true, + "preserveConstEnums": true, + "sourceMap": true, + "outFile": "../../built/local/tsc.js", + "allowJs": true + }, + "exclude": [ + "node_modules", + "**/*.spec.ts" + ], + "include": [ + "src/**/*", + "wailsjs/**/*.ts" + ] +} +``` +Isso deve permitir que você use Vetur como esperado. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx new file mode 100644 index 00000000000..40a4256d3f9 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx @@ -0,0 +1,58 @@ +# Instalador NSIS + +```mdx-code-block +

+ +
+

+``` + +O Wails suporta a geração de instaladores do Windows usando o [instalador do NSIS](https://nsis.sourceforge.io/). + +## Installing NSIS + +### Windows + +O instalador está disponível na página de [Download do NSIS](https://nsis.sourceforge.io/Download). + +Se você usar o gerenciador de pacotes de chocolatey, execute o seguinte script: + +``` +choco install nsis +``` + +Se você instalar o NSIS manualmente, você precisará adicionar a pasta _Bin_, que contém `makensis.exe`, e sua instalação NSIS ao seu PATH. [Aqui](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/) está um bom tutorial sobre como adicionar ao PATH no Windows. + +### Linux + +O pacote `nsis` deve estar disponível através do gerenciador de pacotes da sua distribuição. + +### MacOS + +O NSIS está disponível para instalação através de homebrew: `brew install nsis`. + +## Gerando o instalador + +Quando um novo projeto é criado, o Wails gera os arquivos de configuração do NSIS em `build/windows/installer`. Os dados de configuração são lidos do `installer/info.json` e estão configurados para usar a seção de informação do projeto `wails.json`: + +```json +// ... + "Info": { + "companyName": "My Company Name", + "productName": "Wails Vite", + "productVersion": "1.0.0", + "copyright": "Copyright.........", + "comments": "Built using Wails (https://wails.io)" + }, +``` + +Para gerar um instalador para o seu aplicativo, use a flag `-nsis` com o comando `wails build`: + +``` +wails build -nsis +``` + +O instalador agora estará disponível no diretório `build/bin`. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx new file mode 100644 index 00000000000..dd76db15adb --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx @@ -0,0 +1,61 @@ +# Windows + +Esta página tem guias diversos relacionados ao desenvolvimento de aplicativos Wails para Windows. + +## Manipulando a dependência de runtime WebView2, + +Aplicativos de Wails feitos para Windows possuem uma exigência de tempo de execução na Microsoft [Runtime WebView2](https://developer.microsoft.com/en-us/microsoft-edge/webview2/). Windows 11 terá isto instalado por padrão, mas algumas máquinas não. O Wails oferece uma abordagem fácil para lidar com esta dependência. + +Usando a flag `-webview2` ao realizar o build, você pode decidir o que sua aplicação fará quando não for detectado um tempo de execução adequado (incluindo se o tempo de execução instalado for muito antigo). As quatro opções são: + +1. Baixar +2. Incorporar +3. Navegador +4. Erro + +### Baixar + +Esta opção irá solicitar ao usuário que nenhum tempo de execução adequado foi encontrado e, em seguida, oferecer para baixar e executar o bootstrapper oficial no site WebView2 da Microsoft. Se o usuário continuar, o bootstrapper oficial será baixado e executado. + +### Incorporar + +Esta opção incorpora o bootstrapper oficial dentro do aplicativo. Se nenhum tempo de execução adequado for encontrado, o aplicativo oferecerá para executar o bootstrapper. Isto adiciona ~150k ao tamanho do binário. + +### Navegador + +Esta opção pedirá ao usuário que nenhum tempo de execução adequado foi encontrado e, em seguida, oferecerá para abrir um navegador na página oficial WebView2, onde o bootstrapper pode ser baixado e instalado. O aplicativo irá então sair, deixando a instalação para o usuário. + +### Erro + +Se não for encontrado um tempo de execução adequado, um erro é dado ao usuário e nenhuma ação foi feita. + +## Execução da versão fixa + +Outra forma de lidar com a dependência webview2 é enviando-a você mesmo. Você pode baixar [versão fixa em tempo de execução](https://developer.microsoft.com/microsoft-edge/webview2/#download-section) e empacotar ou baixá-lo com seu aplicativo. + +Além disso, você deve especificar o caminho para a versão fixa do tempo de execução webview2 nas `windows.Options` structure ao iniciar wails. + +```go + wails.Run(&options.App{ + Windows: &windows.Options{ + WebviewBrowserPath: "", + }, + }) +``` + +Observação: Quando `WebviewBrowserPath` é especificado a estratégia `error` seráforçada em caso de exigência de versão mínima ou erros na busca do runtime. + +## Gerando outros programas + +Ao gerar outros programas, tais como scripts, você verá a janela aparecer na tela. Para ocultar a janela, você pode usar o seguinte código: + +```go +cmd := exec.Command("your_script.exe") +cmd.SysProcAttr = &syscall.SysProcAttr{ + HideWindow: true, + CreationFlags: 0x08000000, +} +cmd.Start() +``` + +Solução fornecida pelo [sithembiso](https://github.com/sithembiso) no [quadro de discussões](https://github.com/wailsapp/wails/discussions/1734#discussioncomment-3386172). diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx new file mode 100644 index 00000000000..44fa130cc74 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx @@ -0,0 +1,369 @@ +--- +sidebar_position: 20 +--- + +# How does it work? + +A Wails application is a standard Go application, with a webkit frontend. The Go part of the application consists of the application code and a runtime library that provides a number of useful operations, like controlling the application window. The frontend is a webkit window that will display the frontend assets. Also available to the frontend is a JavaScript version of the runtime library. Finally, it is possible to bind Go methods to the frontend, and these will appear as JavaScript methods that can be called, just as if they were local JavaScript methods. + +```mdx-code-block +
+ +
+``` + +## The Main Application + +### Overview + +The main application consists of a single call to `wails.Run()`. It accepts the application configuration which describes the size of the application window, the window title, what assets to use, etc. A basic application might look like this: + +```go title="main.go" +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + + app := &App{} + + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + + +type App struct { + ctx context.Context +} + +func (b *App) startup(ctx context.Context) { + b.ctx = ctx +} + +func (b *App) shutdown(ctx context.Context) {} + +func (b *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +### Options rundown + +This example has the following options set: + +- `Title` - The text that should appear in the window's title bar +- `Width` & `Height` - The dimensions of the window +- `Assets` - The application's frontend assets +- `OnStartup` - A callback for when the window is created and is about to start loading the frontend assets +- `OnShutdown` - A callback for when the application is about to quit +- `Bind` - A slice of struct instances that we wish to expose to the frontend + +A full list of application options can be found in the [Options Reference](reference/options). + +#### Assets + +The `Assets` option is mandatory as you can't have a Wails application without frontend assets. Those assets can be any files you would expect to find in a web application - html, js, css, svg, png, etc. **There is no requirement to generate asset bundles** - plain files will do. When the application starts, it will attempt to load `index.html` from your assets and the frontend will essentially work as a browser from that point on. It is worth noting that there is no requirement on where in the `embed.FS` the files live. It is likely that the embed path uses a nested directory relative to your main application code, such as `frontend/dist`: + +```go title="main.go" +//go:embed all:frontend/dist +var assets embed.FS +``` + +At startup, Wails will iterate the embedded files looking for the directory containing `index.html`. All other assets will be loaded relative to this directory. + +As production binaries use the files contained in `embed.FS`, there are no external files required to be shipped with the application. + +When running in development mode using the `wails dev` command, the assets are loaded off disk, and any changes result in a "live reload". The location of the assets will be inferred from the `embed.FS`. + +More details can be found in the [Application Development Guide](guides/application-development.mdx). + +#### Application Lifecycle Callbacks + +Just before the frontend is about to load `index.html`, a callback is made to the function provided in [OnStartup](reference/options.mdx#onstartup). A standard Go context is passed to this method. This context is required when calling the runtime so a standard pattern is to save a reference to in this method. Just before the application shuts down, the [OnShutdown](reference/options.mdx#onshutdown) callback is called in the same way, again with the context. There is also an [OnDomReady](reference/options.mdx#ondomready) callback for when the frontend has completed loading all assets in `index.html` and is equivalent of the [`body onload`](https://www.w3schools.com/jsref/event_onload.asp) event in JavaScript. It is also possible to hook into the window close (or application quit) event by setting the option [OnBeforeClose](reference/options.mdx#onbeforeclose). + +#### Method Binding + +The `Bind` option is one of the most important options in a Wails application. It specifies which struct methods to expose to the frontend. Think of structs like "controllers" in a traditional web application. When the application starts, it examines the struct instances listed in the `Bind` field in the options, determines which methods are public (starts with an uppercase letter) and will generate JavaScript versions of those methods that can be called by the frontend code. + +:::info Note + +Wails requires that you pass in an _instance_ of the struct for it to bind it correctly + +::: + +In this example, we create a new `App` instance and then add this instance to the `Bind` option in `wails.Run`: + +```go {17,27} title="main.go" +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + + app := &App{} + + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + + +type App struct { + ctx context.Context +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +You may bind as many structs as you like. Just make sure you create an instance of it and pass it in `Bind`: + +```go {10-12} + //... + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + &mystruct1{}, + &mystruct2{}, + }, + }) + +``` + +When you run `wails dev` (or `wails generate module`), a frontend module will be generated containing the following: + +- JavaScript bindings for all bound methods +- TypeScript declarations for all bound methods +- TypeScript definitions for all Go structs used as inputs or outputs by the bound methods + +This makes it incredibly simple to call Go code from the frontend, using the same strongly typed datastructures. + +## The Frontend + +### Overview + +The frontend is a collection of files rendered by webkit. It's like a browser and webserver in one. There is virtually[^1] no limit to which frameworks or libraries you can use. The main points of interaction between the frontend and your Go code are: + +- Calling bound Go methods +- Calling runtime methods + +### Calling bound Go methods + +When you run your application with `wails dev`, it will automatically generate JavaScript bindings for your structs in a directory called `wailsjs/go` (You can also do this by running `wails generate module`). The generated files mirror the package names in your application. In the example above, we bind `app`, which has one public method `Greet`. This will lead to the generation of the following files: + +```bash +wailsjs + └─go + └─main + ├─App.d.ts + └─App.js +``` + +Here we can see that there is a `main` package that contains the JavaScript bindings for the bound `App` struct, as well as the TypeScript declaration file for those methods. To call `Greet` from our frontend, we simply import the method and call it like a regular JavaScript function: + +```javascript +// ... +import { Greet } from "../wailsjs/go/main/App"; + +function doGreeting(name) { + Greet(name).then((result) => { + // Do something with result + }); +} +``` + +The TypeScript declaration file gives you the correct types for the bound methods: + +```ts +export function Greet(arg1: string): Promise; +``` + +The generated methods return a Promise. A successful call will result in the first return value from the Go call to be passed to the `resolve` handler. An unsuccessful call is when a Go method that has an error type as it's second return value, passes an error instance back to the caller. This is passed back via the `reject` handler. In the example above, `Greet` only returns a `string` so the JavaScript call will never reject - unless invalid data is passed to it. + +All data types are correctly translated between Go and JavaScript. Even structs. If you return a struct from a Go call, it will be returned to your frontend as a JavaScript class. + +:::info Note + +Struct fields _must_ have a valid `json` tag to be included in the generated TypeScript. + +Anonymous nested structs are not supported at this time. + +::: + +It is possible to send structs back to Go. Any JavaScript map/class passed as an argument that is expecting a struct, will be converted to that struct type. To make this process a lot easier, in `dev` mode, a TypeScript module is generated, defining all the struct types used in bound methods. Using this module, it's possible to construct and send native JavaScript objects to the Go code. + +There is also support for Go methods that use structs in their signature. All Go structs specified by a bound method (either as parameters or return types) will have TypeScript versions auto generated as part of the Go code wrapper module. Using these, it's possible to share the same data model between Go and JavaScript. + +Example: We update our `Greet` method to accept a `Person` instead of a string: + +```go title="main.go" +type Person struct { + Name string `json:"name"` + Age uint8 `json:"age"` + Address *Address `json:"address"` +} + +type Address struct { + Street string `json:"street"` + Postcode string `json:"postcode"` +} + +func (a *App) Greet(p Person) string { + return fmt.Sprintf("Hello %s (Age: %d)!", p.Name, p.Age) +} +``` + +The `wailsjs/go/main/App.js` file will still have the following code: + +```js title="App.js" +export function Greet(arg1) { + return window["go"]["main"]["App"]["Greet"](arg1); +} +``` + +But the `wailsjs/go/main/App.d.ts` file will be updated with the following code: + +```ts title="App.d.ts" +import { main } from "../models"; + +export function Greet(arg1: main.Person): Promise; +``` + +As we can see, the "main" namespace is imported from a new "models.ts" file. This file contains all the struct definitions used by our bound methods. In this example, this is a `Person` struct. If we look at `models.ts`, we can see how the models are defined: + +```ts title="models.ts" +export namespace main { + export class Address { + street: string; + postcode: string; + + static createFrom(source: any = {}) { + return new Address(source); + } + + constructor(source: any = {}) { + if ("string" === typeof source) source = JSON.parse(source); + this.street = source["street"]; + this.postcode = source["postcode"]; + } + } + export class Person { + name: string; + age: number; + address?: Address; + + static createFrom(source: any = {}) { + return new Person(source); + } + + constructor(source: any = {}) { + if ("string" === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.age = source["age"]; + this.address = this.convertValues(source["address"], Address); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice) { + return (a as any[]).map((elem) => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } +} +``` + +So long as you have TypeScript as part of your frontend build configuration, you can use these models in the following way: + +```js title="mycode.js" +import { Greet } from "../wailsjs/go/main/App"; +import { main } from "../wailsjs/go/models"; + +function generate() { + let person = new main.Person(); + person.name = "Peter"; + person.age = 27; + Greet(person).then((result) => { + console.log(result); + }); +} +``` + +The combination of generated bindings and TypeScript models makes for a powerful development environment. + +More information on Binding can be found in the [Binding Methods](guides/application-development.mdx#binding-methods) section of the [Application Development Guide](guides/application-development.mdx). + +### Calling runtime methods + +The JavaScript runtime is located at `window.runtime` and contains many methods to do various tasks such as emit an event or perform logging operations: + +```js title="mycode.js" +window.runtime.EventsEmit("my-event", 1); +``` + +More details about the JS runtime can be found in the [Runtime Reference](reference/runtime/intro). + +[^1]: There is a very small subset of libraries that use features unsupported in WebViews. There are often alternatives and workarounds for such cases. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx new file mode 100644 index 00000000000..f25eaba30c2 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx @@ -0,0 +1,75 @@ +--- +sidebar_position: 1 +--- + +# Introdução + +Wails é um projeto que permite a você escrever aplicativos de desktop usando Go e web. + +Considere uma alternativa leve e rápida do Electron para o Go. Você pode facilmente construir aplicativos com a flexibilidade e o poder do Go, combinados com um frontend rico e moderno. + +### Funcionalidades + +- Menus Nativos, Dialogs, Temas e Transparência +- Suporte a Windows, macOS e Linux +- Modelos embutidos para Svelte, React, Preact, Vue, Lit e Vanilla JS +- Easily call Go methods from JavaScript +- Automatic Go struct to TypeScript model generation +- Não são necessárias DLLs externas ou CGO no Windows +- Modo de desenvolvimento ao vivo usando o poder do [Vite](https://vitejs.dev/) +- Poderoso CLI para criar, Construir e Empacotar facilmente +- Uma rica [biblioteca de tempo de execução](/docs/reference/runtime/intro) +- Aplicativos construídos com Wails são compatíveis com Apple & Microsoft Store + +Este é [vago](https://varly.app) - um aplicativo para desktop para MacOS & Windows escrito usando Wails. Não só parece ótimo, como também usa menus nativos e translucidez - tudo o que você esperaria de um aplicativo nativo moderno. + +```mdx-code-block +

+ + + +

+``` + +### Criação Rápida de Template + +Há uma série de modelos pré-configurados que permitem que o aplicativo entre em funcionamento rapidamente. Há modelos para os seguintes frameworks: Svelte, React, Vue, Preact, Lit e Vanilla. There are both JavaScript and TypeScript versions for each template. + +### Elementos Nativos + +Wails uses a purpose built library for handling native elements such as Window, Menus, Dialogs, etc, so you can build good-looking, feature rich desktop applications. + +**It does not embed a browser**, so it delivers a small runtime. Instead, it reuses the native rendering engine for the platform. No Windows, esta é a nova biblioteca da Microsoft Webview2, construída no Chromium. + +### Go & JavaScript Interoperability + +Wails automatically makes your Go methods available to JavaScript, so you can call them by name from your frontend! It even generates TypeScript models for the structs used by your Go methods, so you can pass the same data structures between Go and JavaScript. + +### Biblioteca de tempo de execução + +Wails provides a runtime library, for both Go and JavaScript, that handles a lot of the things modern applications need, like Eventing, Logging, Dialogs, etc. + +### Experiência de Desenvolvimento Ao Vivo + +#### Reconstruções automáticas + +Quando você executar seu aplicativo no modo "dev", o Wails construirá seu aplicativo como uma aplicação de desktop nativa, e lerá seus ativos a partir do disco. Ele detectará quaisquer alterações no seu Código Go e reconstruirá automaticamente e reiniciará seu aplicativo. + +#### Recarregamentos automáticos + +Quando alterações nos assets de seu aplicativo forem detectadas, seu aplicativo em execução irá "recarregar", reflectindo suas alterações quase imediatamente. + +#### Desenvolva sua aplicação com um navegador + +If you prefer to debug and develop in a browser then Wails has you covered. The running application also has a webserver that will run your application in any browser that connects to it. It will even refresh when your assets change on disk. + +### Production-ready Native Binaries + +When you're ready to do the final build of your application, the CLI will compile it down to a single executable, with all the assets bundled into it. On Windows and MacOS, it is possible to create a native package for distribution. The assets used in packaging (icon, info.plist, manifest file, etc) are part of your project and may be customised, giving you total control over how your applications are built. + +### Tooling + +The Wails CLI provides a hassle-free way to generate, build and bundle your applications. It will do the heavy lifting of creating icons, compiling your application with optimal settings and delivering a distributable, production ready binary. Choose from a number of starter templates to get up and running quickly! diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx new file mode 100644 index 00000000000..c2a5d706bac --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx @@ -0,0 +1,240 @@ +--- +sidebar_position: 2 +--- + +# Linha de comandos + +A CLI do Wails tem vários comandos que são usados para gerenciar seus projetos. Todos os comandos são executados da seguinte maneira: + +`wails ` + +## init + +`wails init` é usado para gerar projetos. + +| Flag | Descrição | Padrão | +|:------------------------- |:---------------------------------------------------------------------------------------------------------------------------------- |:---------------:| +| -n "nome do projeto" | Nome do projeto. **Obrigatório**. | | +| -d "diretório do projeto" | Diretório de projeto a criar | Nome do projeto | +| -g | Inicializar o repositório git | | +| -l | Listar modelos de projetos disponíveis | | +| -q | Suprimir saída no console | | +| -t "nome do template" | O modelo do projeto a ser usado. Este pode ser o nome de um template padrão ou um URL para um template remoto hospedado no github. | vanilla | +| -ide | Gerar arquivos de projeto IDE | | +| -f | Forçar compilação de aplicação | false | + +Exemplo: `wails init -n test -d mytestproject -g -ide vscode -q` + +Isso irá gerar um projeto chamado "test" no diretório "mytestproject", inicializar o git, gerar arquivos de projeto vscode e fazê-lo silenciosamente. + +Mais informações sobre isso podem ser encontradas [aqui](../guides/ides.mdx). + +### Modelos Remotos + +Modelos remotos (hospedados no GitHub) são suportados e podem ser instalados usando a URL do projeto do template. + +Exemplo: `wails init -n teste -t https://github.com/leaanthony/testtemplate[@v1.0.0]` + +Uma lista de modelos mantidos pela comunidade pode ser encontrada [aqui](../community/templates.mdx) + +:::warning Attention + +**The Wails project does not maintain, is not responsible nor liable for 3rd party templates!** + +If you are unsure about a template, inspect `package.json` and `wails.json` for what scripts are run and what packages are installed. + +::: + +## build + +`wails build` é usado para compilar seu projeto para um binário pronto para produção. + +| Flag | Descrição | Padrão | +|:-------------------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |:----------------------------------------------------------------------------------------------------------------------------------------------------- | +| -clean | Limpa o diretório `compilação/bin` | | +| -compiler "compiler" | Use um compilador de ida diferente para realizar build, por exemplo, go1.15beta1 | go | +| -debug | Retains debug information in the application and shows the debug console. Permite o uso das ferramentas devtools na janela do aplicativo | | +| -devtools | Allows the use of the devtools in the application window in production (when -debug is not used). Ctrl/Cmd+Shift+F12 may be used to open the devtools window. *NOTE*: This option will make your application FAIL Mac appstore guidelines. Use for debugging only. | | +| -dryrun | Prints the build command without executing it | | +| -f | Forçar compilação de aplicação | | +| -garbleargs | Argumentos para passar para o garble | `-literals -tiny -seed=random` | +| -ldflags "flags" | Ldflags adicionais para passar para o compilador | | +| -m | Skip mod tidy before compile | | +| -nopackage | Não empacotar aplicação | | +| -nocolour | Disable colour in output | | +| -nosyncgomod | Do not sync go.mod with the Wails version | | +| -nsis | Generate NSIS installer for Windows | | +| -o nome de arquivo | Nome do Arquivo de Saída | | +| -obfuscated | Ofuscar a aplicação usando [garble](https://github.com/burrowers/garble) | | +| -platform | Compila para as plataformas [(delimitadas por vírgula)](../reference/cli.mdx#platforms) por exemplo. `windows/arm64`. Note, se você não der arquitetura, `runtime.GOARCH` é usado. | platform = `variável de ambiente GOOS` se determinado `runtime.GOOS`.
arch = `GOARCH` variável de envrionment se for dado `runtime.GOARCH`. | +| -race | Realiza build com o Go race detector | | +| -s | Pular build do frontend | | +| -skipbindings | Skip bindings generation | | +| -tags "extra tags" | Compilar tags para passar para o compilador Go. Deve ser citado. Separados por espaço ou vírgula (mas não ambos) | | +| -trimpath | Remove todos os caminhos do sistema de arquivo do executável resultante. | | +| -u | Atualiza o `go.mod` do seu projeto para usar a mesma versão de Wails que o CLI | | +| -upx | Comprimir binário final usando "upx" | | +| -upxflags | Flags para passar para o upx | | +| -v int | Nível de verbosidade(0 - silencioso, 1 - padrão, 2 - verbose) | 1 | +| -webview2 | Estratégia de instalação WebView2: download,embed,browser,error | baixar | +| -windowsconsole | Manter a janela de console para builds do Windows | | + +Para uma descrição detalhada do sinalizador `webview2`, consulte o guia [Windows](../guides/windows.mdx). + +Se você preferir construir usando a ferramenta Go padrão, consulte o guia de [Builds Manuais](../guides/manual-builds.mdx). + +Exemplo: + +`wails build -clean -o myproject.exe` + +:::info + +On Mac, the application will be bundled with `Info.plist`, not `Info.dev.plist`. + +::: + +:::info UPX no Apple Silicon + +Há alguns [problemas](https://github.com/upx/upx/issues/446) com o uso de UPX com o Apple Silicon. + +::: + +:::info UPX no Windows + +Alguns fornecedores de antivírus marcam como falsos positivos os binários `upx` comprimidos como vírus, veja [problema](https://github.com/upx/upx/issues/437). + +::: + +### Plataformas + +Plataformas Suportadas: + +| Plataforma | Descrição | +|:---------------- |:--------------------------------------------- | +| darwin | MacOS + architecture of build machine | +| darwin/amd64 | MacOS 10.13+ AMD64 | +| darwin/arm64 | MacOS 11.0+ ARM64 | +| darwin/universal | MacOS AMD64+ARM64 universal application | +| windows | Windows 10/11 + architecture of build machine | +| windows/amd64 | Windows 10/11 AMD64 | +| windows/arm64 | Windows 10/11 ARM64 | +| linux | Linux + architecture of build machine | +| linux/amd64 | Linux AMD64 | +| linux/arm64 | Linux ARM64 | + +## doctor + +`wails doctor` executará o diagnóstico para garantir que seu sistema esteja pronto para desenvolvimento. + +Exemplo: + +``` +Wails CLI v2.0.0-beta + +Scanning system - Please wait (this may take a long time)...Done. + +System +------ +OS: Windows 10 Pro +Version: 2009 (Build: 19043) +ID: 21H1 +Go Version: go1.18 +Platform: windows +Architecture: amd64 + +Dependency Package Name Status Version +---------- ------------ ------ ------- +WebView2 N/A Installed 93.0.961.52 +npm N/A Installed 6.14.15 +*upx N/A Installed upx 3.96 + +* - Optional Dependency + +Diagnosis +--------- +Your system is ready for Wails development! + +``` + +## dev + +`wails dev` é usado para executar sua aplicação em um modo de "desenvolvimento ao vivo". Isso significa que: + +- O aplicativo `go.mod` será atualizado para usar a mesma versão do Wails como a CLI +- A aplicação é compilada e executada automaticamente +- Um observador é iniciado e acionará uma reconstrução do seu aplicativo de desenvolvimento se ele detectar alterações em seus arquivos go +- Um servidor web foi iniciado em `http://localhost:34115` que serve sua aplicação (não apenas frontend) sobre http. Isso permite que você use suas extensões de desenvolvimento de navegador favoritas +- Todos os conteúdos do aplicativo são carregados do disco. Se forem alterados, o aplicativo irá recarregar automaticamente (não reconstruir). Todos os navegadores conectados também recarregarão +- A JS module is generated that provides the following: +- JavaScript wrappers of your Go methods with autogenerated JSDoc, providing code hinting +- TypeScript versions of your Go structs, that can be constructed and passed to your go methods +- A second JS module is generated that provides a wrapper + TS declaration for the runtime +- On macOS, it will bundle the application into a `.app` file and run it. It will use a `build/darwin/Info.dev.plist` for development. + +| Flag | Descrição | Padrão | +|:--------------------------------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------- |:--------------------- | +| -appargs "args" | Argumentos passados para o aplicativo no estilo shell | | +| -assetdir "./caminho/para/midias" | Serve os arquivos a partir do diretório fornecido em vez de usar os arquivos FS fornecidos | Valor em `wails.json` | +| -browser | Abre um navegador para `http://localhost:34115` na inicialização | | +| -compiler "compiler" | Use um compilador de ida diferente para realizar build, por exemplo, go1.15beta1 | go | +| -debounce | O tempo de esperar por recarregar depois que uma alteração de ativo for detectada | 100 (milliseconds) | +| -devserver "host:port" | O endereço para vincular o servidor de desenvolvimento de wails a | "localhost:34115" | +| -extensions | Extensões para acionar reconstruções (separadas por vírgula) | go | +| -forcebuild | Force build of application | | +| -frontenddevserverurl "url" | Usar URL do servidor de desenvolvimento de terceiros para servir midias, Vite EG | "" | +| -ldflags "flags" | Ldflags adicionais para passar para o compilador | | +| -loglevel "loglevel" | Nível de log a ser usado - Trace, Debug, Info, Warning, Error | Debug | +| -nocolour | Desativar saída da colorida da cli | false | +| -noreload | Desativar a recarga automática quando os arquivos forem alterados | | +| -nosyncgomod | Do not sync go.mod with the Wails version | false | +| -race | Realiza build com o Go race detector | false | +| -reloaddirs | Diretórios adicionais para acionar recarregamentos (separados por vírgula) | Valor em `wails.json` | +| -s | Pular build do frontend | false | +| -save | Salva o `assetdir`, `reloaddirs`,`wailsjsdir`,`debounce`,`devserver` e `frontenddevserverurl` passado, flag em `wails.json` para realizar chamadas subsequentes. | | +| -skipbindings | Skip bindings generation | | +| -tags "extra tags" | Compilar tags para passar para o compilador (citado e espaço separado) | | +| -v | Nível de verbosidade(0 - silencioso, 1 - padrão, 2 - verbose) | 1 | +| -wailsjsdir | O diretório para gerar os módulos gerados do Wails JS | Valor em `wails.json` | + +Exemplo: + +`wails dev -assetdir ./frontend/dist -wailsjsdir ./frontend/src -browser` + +Este comando fará o seguinte: + +- Compilação do aplicativo e execução (mais detalhes [aqui](../guides/manual-builds.mdx) +- Gerar os módulos JS de Wails em `./frontend/src` +- Assistir por atualizações em arquivos em `./frontend/dist` e recarregar em qualquer alteração +- Abrir um navegador e conectar-se ao aplicativo + +Há mais informações sobre como usar este recurso com scripts de framework existentes [aqui](../guides/application-development.mdx#live-reloading). + +## generate + +### template + +A Wails usa modelos para a geração de projeto. O comando `wails generate template` ajuda a fazer um template para que ele possa ser usado para gerar projetos. + +| Flag | Descrição | +|:---------------- |:----------------------------------------------------- | +| -name | O nome do template (Obrigatório) | +| -frontend "path" | Caminho para o projeto frontend para usar no template | + +Para mais detalhes sobre a criação de modelos, consulte o [guia de Modelos](../guides/templates.mdx). + +### module + +O comando `wails generate template` permite que você gere manualmente o diretório `wailsjs` para o seu aplicativo. + +## update + +`wails update` irá atualizar a versão da CLI do Wails. + +| Flag | Descrição | +|:------------------ |:------------------------------------- | +| -pre | Atualizar para a versão mais recente | +| -version "version" | Instalar uma versão específica do CLI | + +## version + +`wails version` simplesmente irá retornar a versão CLI atual. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx new file mode 100644 index 00000000000..a60919a04b3 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx @@ -0,0 +1,230 @@ +--- +sidebar_position: 4 +--- + +# Menus + +É possível adicionar um menu de aplicação aos projetos do Wails. Isso é conseguido definindo uma struct [Menu](#menu) e configurando-a no configuração do aplicativo [`Menu`](../reference/options.mdx#menu) ou chamando o método [MenuSetApplicationMenu](../reference/runtime/menu.mdx#menusetapplicationmenu). + +Um exemplo de como criar um menu: + +```go + + app := NewApp() + + AppMenu := menu.NewMenu() + FileMenu := AppMenu.AddSubmenu("File") + FileMenu.AddText("&Open", keys.CmdOrCtrl("o"), openFile) + FileMenu.AddSeparator() + FileMenu.AddText("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) { + runtime.Quit(app.ctx) + }) + + if runtime.GOOS == "darwin" { + AppMenu.Append(menu.EditMenu()) // on macos platform, we should append EditMenu to enable Cmd+C,Cmd+V,Cmd+Z... shortcut + } + + err := wails.Run(&options.App{ + Title: "Menus Demo", + Width: 800, + Height: 600, + Menu: AppMenu, // reference the menu above + Bind: []interface{}{ + app, + }, + ) + // ... +``` + +Também é possível atualizar dinamicamente o menu, atualizando o menu struct e chamando [MenuUpdateApplicationMenu](../reference/runtime/menu.mdx#menuupdateapplicationmenu). + +O exemplo acima usa métodos de ajuda, no entanto, é possível construir as construções do menu manualmente. + +## Menu + +Um Menu é uma coleção de MenuItems: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +type Menu struct { + Items []*MenuItem +} +``` + +Para o menu de Aplicação, cada MenuItem representa um único menu como "Editar". + +Um método simples de ajuda é fornecido para menus de construção: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func NewMenuFromItems(first *MenuItem, rest ...*MenuItem) *Menu +``` + +Isto torna o layout do código mais parecido com o de um menu sem a necessidade de adicionar os itens de menu manualmente depois de criá-los. Como alternativa, você pode apenas criar os itens de menu e adicioná-los ao menu manualmente. + +## MenuItem + +Um MenuItem representa um item dentro de um Menu. + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +// MenuItem represents a menu item contained in a menu +type MenuItem struct { + Label string + Role Role + Accelerator *keys.Accelerator + Type Type + Disabled bool + Hidden bool + Checked bool + SubMenu *Menu + Click Callback +} +``` + +| Campo | Tipo | Notas | +| ----------- | ------------------------------------ | -------------------------------------------------------------------------- | +| Label | string | O texto do menu | +| Accelerator | [\*keys.Accelerator](#accelerator) | Vinculação de teclas para este item de menu | +| Tipo | [Tipo](#type) | Tipo de MenuItem | +| Disabled | bool | Desativa o item de menu | +| Hidden | bool | Oculta este item de menu | +| Checked | bool | Adiciona uma seleção para o item ( & Tipos de Rádio) | +| SubMenu | [\*Menu](#menu) | Define o submenu | +| Click | [Callback](#callback) | Função Callback quando clicado no menu | +| Role | string | Define um papel [](#role) para este item de menu. Mac apenas por enquanto. | + +### Accelerator + +Os aceleradores (às vezes chamados atalhos de teclado) definem uma ligação entre um toque de tecla e um item de menu. Lamentos define um Acelerador como uma combinação ou tecla + [Modificador](#modifier). Eles estão disponíveis no pacote `"github.com/wailsapp/wails/v2/pkg/menu/keys"`. + +Exemplo: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines cmd+o on Mac and ctrl-o on Window/Linux + myShortcut := keys.CmdOrCtrl("o") +``` + +Teclas são qualquer caractere único em um teclado com exceção de `+`, que é definido como `plus`. Algumas chaves não podem ser representadas como caracteres, portanto há um conjunto de caracteres nomeados que podem ser usados: + +| | | | | +|:-----------:|:-----:|:-----:|:---------:| +| `backspace` | `f1` | `f16` | `f31` | +| `tab` | `f2` | `f17` | `f32` | +| `return` | `f3` | `f18` | `f33` | +| `enter` | `f4` | `f19` | `f34` | +| `escape` | `f5` | `f20` | `f35` | +| `left` | `f6` | `f21` | `numlock` | +| `right` | `f7` | `f22` | | +| `up` | `f8` | `f23` | | +| `down` | `f9` | `f24` | | +| `space` | `f10` | `f25` | | +| `delete` | `f11` | `f36` | | +| `home` | `f12` | `f37` | | +| `end` | `f13` | `f38` | | +| `page up` | `f14` | `f39` | | +| `page down` | `f15` | `f30` | | + +Wails também suportam a análise de aceleradores usando a mesma sintaxe que o Electron. Isso é útil para armazenar aceleradores em arquivos de configuração. + +Exemplo: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines cmd+o on Mac and ctrl-o on Window/Linux + myShortcut, err := keys.Parse("Ctrl+Option+A") +``` + +#### Modificador + +Os seguintes modificadores são chaves que podem ser usadas em combinação com a tecla de aceleração: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" +const ( + // CmdOrCtrlKey represents Command on Mac and Control on other platforms + CmdOrCtrlKey Modifier = "cmdorctrl" + // OptionOrAltKey represents Option on Mac and Alt on other platforms + OptionOrAltKey Modifier = "optionoralt" + // ShiftKey represents the shift key on all systems + ShiftKey Modifier = "shift" + // ControlKey represents the control key on all systems + ControlKey Modifier = "ctrl" +) +``` + +Vários métodos de ajuda estão disponíveis para criar aceleradores usando modificadores: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" +func CmdOrCtrl(key string) *Accelerator +func OptionOrAlt(key string) *Accelerator +func Shift(key string) *Accelerator +func Control(key string) *Accelerator +``` + +Modificadores podem ser combinados usando `keys.Combo(string de chaves, modificador 1 modificador, modificador modificador, rest ...Modificador)`: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines "Ctrl+Option+A" on Mac and "Ctrl+Alt+A" on Window/Linux + myShortcut := keys.Combo("a", ControlKey, OptionOrAltKey) +``` + +### Tipo + +Cada item de menu deve ter um tipo e existem 5 tipos disponíveis: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +const ( + TextType Type = "Text" + SeparatorType Type = "Separator" + SubmenuType Type = "Submenu" + CheckboxType Type = "Checkbox" + RadioType Type = "Radio" +) +``` + +Para conveniência, métodos auxiliares são fornecidos para criar rapidamente um item de menu: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func Text(label string, accelerator *keys.Accelerator, click Callback) *MenuItem +func Separator() *MenuItem +func Radio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func Checkbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func SubMenu(label string, menu *Menu) *Menu +``` + +Você também pode criar itens de menu diretamente em um menu, usando os ajudantes "Adicionar": + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func (m *Menu) AddText(label string, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddSeparator() *MenuItem +func (m *Menu) AddRadio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddCheckbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddSubMenu(label string, menu *Menu) *MenuI +``` + +Uma nota nos grupos de rádio: Um grupo de rádio é definido como um número de itens do menu de rádio que estão próximos um ao outro no menu. Isso significa que não é necessário agrupar os itens porque é automático. No entanto, isso também significa que você não pode ter 2 grupos lado a lado - deve haver um item que não seja de rádio entre eles. + +### Callback + +Cada item de menu pode ter um callback que é executado quando o item é clicado: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +type Callback func(*CallbackData) + +type CallbackData struct { + MenuItem *MenuItem +} +``` + +A função recebe uma instrução `CallbackData` que indica qual item de menu acionou a callback. Isso é útil quando usar grupos de rádio que podem compartilhar um callback. + +### Role + +:::info Regras + +As regras que são atualmente suportados apenas no Mac. + +::: + +Um item de menu pode ter uma função, que é essencialmente um item de menu pré-definido. Atualmente, apoiamos as seguintes funções: + +| Role | Descrição | +| ------------ | --------------------------------------------------------------------------- | +| AppMenuRole | Menu padrão do aplicativo para Mac. Pode ser criado usando `menu.AppMenu()` | +| EditMenuRole | O menu de edição padrão para Mac. Pode ser criado usando `menu.EditMenu()` | diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx new file mode 100644 index 00000000000..46d1c071b60 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx @@ -0,0 +1,853 @@ +--- +sidebar_position: 3 +--- + +# Options + +## Application Options + +The `Options.App` struct contains the application configuration. It is passed to the `wails.Run()` method: + +```go title="Example" +import ( + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/linux" + "github.com/wailsapp/wails/v2/pkg/options/mac" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +func main() { + + err := wails.Run(&options.App{ + Title: "Menus Demo", + Width: 800, + Height: 600, + DisableResize: false, + Fullscreen: false, + WindowStartState: options.Maximised, + Frameless: true, + MinWidth: 400, + MinHeight: 400, + MaxWidth: 1280, + MaxHeight: 1024, + StartHidden: false, + HideWindowOnClose: false, + BackgroundColour: &options.RGBA{R: 0, G: 0, B: 0, A: 255}, + AlwaysOnTop: false, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: assetsHandler, + Middleware: assetsMidldeware, + }, + Menu: app.applicationMenu(), + Logger: nil, + LogLevel: logger.DEBUG, + LogLevelProduction: logger.ERROR, + OnStartup: app.startup, + OnDomReady: app.domready, + OnShutdown: app.shutdown, + OnBeforeClose: app.beforeClose, + CSSDragProperty: "--wails-draggable", + CSSDragValue: "drag", + EnableDefaultContextMenu: false, + EnableFraudulentWebsiteDetection: false, + ZoomFactor: 1.0, + IsZoomControlEnabled: false, + Bind: []interface{}{ + app, + }, + ErrorFormatter: func(err error) any { return err.Error() }, + Windows: &windows.Options{ + WebviewIsTransparent: false, + WindowIsTranslucent: false, + BackdropType: windows.Mica, + DisableWindowIcon: false, + DisableFramelessWindowDecorations: false, + WebviewUserDataPath: "", + WebviewBrowserPath: "", + Theme: windows.SystemDefault, + CustomTheme: &windows.ThemeSettings{ + DarkModeTitleBar: windows.RGB(20, 20, 20), + DarkModeTitleText: windows.RGB(200, 200, 200), + DarkModeBorder: windows.RGB(20, 0, 20), + LightModeTitleBar: windows.RGB(200, 200, 200), + LightModeTitleText: windows.RGB(20, 20, 20), + LightModeBorder: windows.RGB(200, 200, 200), + }, + // User messages that can be customised + Messages *windows.Messages + // OnSuspend is called when Windows enters low power mode + OnSuspend func() + // OnResume is called when Windows resumes from low power mode + OnResume func(), + WebviewGpuDisabled: false, + }, + Mac: &mac.Options{ + TitleBar: &mac.TitleBar{ + TitlebarAppearsTransparent: true, + HideTitle: false, + HideTitleBar: false, + FullSizeContent: false, + UseToolbar: false, + HideToolbarSeparator: true, + }, + Appearance: mac.NSAppearanceNameDarkAqua, + WebviewIsTransparent: true, + WindowIsTranslucent: false, + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + Linux: &linux.Options{ + Icon: icon, + WindowIsTranslucent: false, + WebviewGpuPolicy: linux.WebviewGpuPolicyAlways, + ProgramName: "wails" + }, + Debug: options.Debug{ + OpenInspectorOnStartup: false, + }, + }) + + if err != nil { + log.Fatal(err) + } +} + +``` + +### Title + +The text shown in the window's title bar. + +Name: Title
Type: `string` + +### Width + +The initial width of the window. + +Name: Width
Type: `int`
Default: 1024. + +### Height + +The initial height of the window. + +Name: Height
Type: `int`
Default: 768 + +### DisableResize + +By default, the main window is resizable. Setting this to `true` will keep it a fixed size. + +Name: DisableResize
Type: `bool` + +### Fullscreen + +Deprecated: Please use [WindowStartState](#windowstartstate). + +### WindowStartState + +Defines how the window should present itself at startup. + +| Value | Win | Mac | Lin | +| ---------- | --- | --- | --- | +| Fullscreen | ✅ | ✅ | ✅ | +| Maximised | ✅ | ✅ | ✅ | +| Minimised | ✅ | ❌ | ✅ | + +Name: WindowStartState
Type: `options.WindowStartState` + +### Frameless + +When set to `true`, the window will have no borders or title bar. Also see [Frameless Windows](../guides/frameless.mdx). + +Name: Frameless
Type: `bool` + +### MinWidth + +This sets the minimum width for the window. If the value given in `Width` is less than this value, the window will be set to `MinWidth` by default. + +Name: MinWidth
Type: `int` + +### MinHeight + +This sets the minimum height for the window. If the value given in `Height` is less than this value, the window will be set to `MinHeight` by default. + +Name: MinHeight
Type: `int` + +### MaxWidth + +This sets the maximum width for the window. If the value given in `Width` is more than this value, the window will be set to `MaxWidth` by default. + +Name: MaxWidth
Type: `int` + +### MaxHeight + +This sets the maximum height for the window. If the value given in `Height` is more than this value, the window will be set to `MaxHeight` by default. + +Name: MaxHeight
Type: `int` + +### StartHidden + +When set to `true`, the application will be hidden until [WindowShow](../reference/runtime/window.mdx#windowshow) is called. + +Name: StartHidden
Type: `bool` + +### HideWindowOnClose + +By default, closing the window will close the application. Setting this to `true` means closing the window will + +hide the window instead. + +Name: HideWindowOnClose
Type: `bool` + +### BackgroundColour + +This value is the default background colour of the window. Example: options.NewRGBA(255,0,0,128) - Red at 50% transparency + +Name: BackgroundColour
Type: `*options.RGBA`
Default: white + +### AlwaysOnTop + +Indicates that the window should stay above other windows when losing focus. + +Name: AlwaysOnTop
Type: `bool` + +### Assets + +Deprecated: Please use Assets on [AssetServer specific options](#assetserver). + +### AssetsHandler + +Deprecated: Please use AssetsHandler on [AssetServer specific options](#assetserver). + +### AssetServer + +This defines AssetServer specific options. It allows to customize the AssetServer with static assets, serving assets dynamically with an `http.Handler` or hook into the request chain with an `assetserver.Middleware`. + +Not all features of an `http.Request` are currently supported, please see the following feature matrix: + +| Feature | Win | Mac | Lin | +| ----------------------- | --- | --- | ------ | +| GET | ✅ | ✅ | ✅ | +| POST | ✅ | ✅ | ✅ [^1] | +| PUT | ✅ | ✅ | ✅ [^1] | +| PATCH | ✅ | ✅ | ✅ [^1] | +| DELETE | ✅ | ✅ | ✅ [^1] | +| Request Headers | ✅ | ✅ | ✅ [^1] | +| Request Body | ✅ | ✅ | ✅ [^2] | +| Request Body Streaming | ✅ | ✅ | ✅ [^2] | +| Response StatusCodes | ✅ | ✅ | ✅ [^1] | +| Response Headers | ✅ | ✅ | ✅ [^1] | +| Response Body | ✅ | ✅ | ✅ | +| Response Body Streaming | ❌ | ✅ | ✅ | +| WebSockets | ❌ | ❌ | ❌ | +| HTTP Redirects 30x | ✅ | ❌ | ❌ | + +Name: AssetServer
Type: `*assetserver.Options` + +#### Assets + +The static frontend assets to be used by the application. + +A GET request is first tried to be served from this `fs.FS`. If the `fs.FS` returns `os.ErrNotExist` for that file, the request handling will fallback to the [Handler](#handler) and tries to serve the GET request from it. + +If set to nil, all GET requests will be forwarded to [Handler](#handler). + +Name: Assets
Type: `fs.FS` + +#### Handler + +The assets handler is a generic `http.Handler` for fallback handling of assets that can't be found. + +The handler will be called for every GET request that can't be served from [Assets](#assets), due to `os.ErrNotExist`. Furthermore all non GET requests will always be served from this Handler. If not defined, the result is the following in cases where the Handler would have been called: + +- GET request: `http.StatusNotFound` +- Other request: `http.StatusMethodNotAllowed` + +NOTE: When used in combination with a Frontend DevServer there might be limitations, eg. Vite serves the index.html on every path, that does not contain a file extension. + +Name: AssetsHandler
Type: `http.Handler` + +#### Middleware + +Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default request handler dynamically, e.g. implement specialized Routing etc. The Middleware is called to build a new `http.Handler` used by the AssetSever and it also receives the default handler used by the AssetServer as an argument. + +If not defined, the default AssetServer request chain is executed. + +Name: Middleware
Type: `assetserver.Middleware` + +### Menu + +The menu to be used by the application. More details about Menus in the [Menu Reference](../reference/runtime/menu.mdx). + +:::note + +On Mac, if no menu is specified, a default menu will be created. + +::: + +Name: Menu
Type: `*menu.Menu` + +### Logger + +The logger to be used by the application. More details about logging in the [Log Reference](../reference/runtime/log.mdx). + +Name: Logger
Type: `logger.Logger`
Default: Logs to Stdout + +### LogLevel + +The default log level. More details about logging in the [Log Reference](../reference/runtime/log.mdx). + +Name: LogLevel
Type: `logger.LogLevel`
Default: `Info` in dev mode, `Error` in production mode + +### LogLevelProduction + +The default log level for production builds. More details about logging in the [Log Reference](../reference/runtime/log.mdx). + +Name: LogLevelProduction
Type: `logger.LogLevel`
Default: `Error` + +### OnStartup + +This callback is called after the frontend has been created, but before `index.html` has been loaded. It is given the application context. + +Name: OnStartup
Type: `func(ctx context.Context)` + +### OnDomReady + +This callback is called after the frontend has loaded `index.html` and its resources. It is given the application context. + +Name: OnDomReady
Type: `func(ctx context.Context)` + +### OnShutdown + +This callback is called after the frontend has been destroyed, just before the application terminates. It is given the application context. + +Name: OnShutdown
Type: `func(ctx context.Context)` + +### OnBeforeClose + +If this callback is set, it will be called when the application is about to quit, either by clicking the window close button or calling `runtime.Quit`. Returning true will cause the application to continue, false will continue shutdown as normal. This is good for confirming with the user that they wish to exit the program. + +Example: + +```go title=windowsapp.go +func (b *App) beforeClose(ctx context.Context) (prevent bool) { + dialog, err := runtime.MessageDialog(ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Quit?", + Message: "Are you sure you want to quit?", + }) + + if err != nil { + return false + } + return dialog != "Yes" +} +``` + +Name: OnBeforeClose
Type: `func(ctx context.Context) bool` + +### CSSDragProperty + +Indicates the CSS property to use to identify which elements can be used to drag the window. Default: `--wails-draggable`. + +Name: CSSDragProperty
Type: `string` + +### CSSDragValue + +Indicates what value the `CSSDragProperty` style should have to drag the window. Default: `drag`. + +Name: CSSDragValue
Type: `string` + +### EnableDefaultContextMenu + +EnableDefaultContextMenu enables the browser's default context-menu in production. + +By default, the browser's default context-menu is only available in development and in a `-debug` [build](../reference/cli.mdx#build) along with the devtools inspector, Using this option you can enable the default context-menu in `production` while the devtools inspector won't be available unless the `-devtools` build flag is used. + +When this option is enabled, by default the context-menu will only be shown for text contexts (where Cut/Copy/Paste is needed), to override this behavior, you can use the CSS property `--default-contextmenu` on any HTML element (including the `body`) with the following values : + +| CSS Style | Behavior | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--default-contextmenu: auto;` | (**default**) will show the default context menu only if :
contentEditable is true OR text has been selected OR element is input or textarea | +| `--default-contextmenu: show;` | will always show the default context menu | +| `--default-contextmenu: hide;` | will always hide the default context menu | + +This rule is inherited like any normal CSS rule, so nesting works as expected. + +:::note +This filtering functionality is only enabled in production, so in development and in debug build, the full context-menu is always available everywhere. +::: + +:::warning +This filtering functionality is NOT a security measure, the developer should expect that the full context-menu could be leaked anytime which could contain commands like (Download image, Reload, Save webpage), if this is a concern, the developer SHOULD NOT enable the default context-menu. +::: + + +Name: EnableDefaultContextMenu
Type: `bool` + +### EnableFraudulentWebsiteDetection + +EnableFraudulentWebsiteDetection enables scan services for fraudulent content, such as malware or phishing attempts. These services might send information from your app like URLs navigated to and possibly other content to cloud services of Apple and Microsoft. + +Name: EnableFraudulentWebsiteDetection
Type: `bool` + +### ZoomFactor + +Name: ZoomFactor
Type: `float64` + +This defines the zoom factor for the WebView2. This is the option matching the Edge user activated zoom in or out. + +### IsZoomControlEnabled + +Name: IsZoomControlEnabled
Type: `bool` + +This enables the zoom factor to be changed by the user. Please note that the zoom factor can be set in the options while disallowing the user to change it at runtime (f.e. for a kiosk application or similar). + +### Bind + +A slice of struct instances defining methods that need to be bound to the frontend. + +Name: Bind
Type: `[]interface{}` + +### ErrorFormatter + +A function that determines how errors are formatted when returned by a JS-to-Go method call. The returned value will be marshalled as JSON. + +Name: ErrorFormatter
Type: `func (error) any` + +### Windows + +This defines [Windows specific options](#windows). + +Name: Windows
Type: `*windows.Options` + +#### WebviewIsTransparent + +Setting this to `true` will make the webview background transparent when an alpha value of `0` is used. This means that if you use `rgba(0,0,0,0)` for `background-color` in your CSS, the host window will show through. Often combined with [WindowIsTranslucent](#WindowIsTranslucent) to make frosty-looking applications. + +Name: WebviewIsTransparent
Type: `bool` + +#### WindowIsTranslucent + +Setting this to `true` will make the window background translucent. Often combined with [WebviewIsTransparent](#WebviewIsTransparent). + +For Windows 11 versions before build 22621, this will use the [BlurBehind](https://learn.microsoft.com/en-us/windows/win32/dwm/blur-ovw) method for translucency, which can be slow. For Windows 11 versions after build 22621, this will enable the newer translucency types that are much faster. By default, the type of translucency used will be determined by Windows. To configure this, use the [BackdropType](#BackdropType) option. + +Name: WindowIsTranslucent
Type: `bool` + +#### BackdropType + +:::note + +Requires Windows 11 build 22621 or later. + +::: + +Sets the translucency type of the window. This is only applicable if [WindowIsTranslucent](#WindowIsTranslucent) is set to `true`. + +Name: BackdropType
Type `windows.BackdropType` + +The value can be one of the following: + +| Value | Description | +| ------- | ----------------------------------------------------------------------------------------- | +| Auto | Let Windows decide which backdrop to use | +| None | Do not use translucency | +| Acrylic | Use [Acrylic](https://learn.microsoft.com/en-us/windows/apps/design/style/acrylic) effect | +| Mica | Use [Mica](https://learn.microsoft.com/en-us/windows/apps/design/style/mica) effect | +| Tabbed | Use Tabbed. This is a backdrop that is similar to Mica. | + +#### DisableWindowIcon + +Setting this to `true` will remove the icon in the top left corner of the title bar. + +Name: DisableWindowIcon
Type: `bool` + +#### DisableFramelessWindowDecorations + +Setting this to `true` will remove the window decorations in [Frameless](#Frameless) mode. This means there will be no 'Aero Shadow' and no 'Rounded Corners' shown for the window. Please note that 'Rounded Corners' are only supported on Windows 11. + +Name: DisableFramelessWindowDecorations
Type: `bool` + +#### WebviewUserDataPath + +This defines the path where the WebView2 stores the user data. If empty `%APPDATA%\[BinaryName.exe]` will be used. + +Name: WebviewUserDataPath
Type: `string` + +#### WebviewBrowserPath + +This defines the path to a directory with WebView2 executable files and libraries. If empty, webview2 installed in the system will be used. + +Important information about distribution of fixed version runtime: + +- [How to get and extract runtime](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#details-about-the-fixed-version-runtime-distribution-mode) +- [Known issues for fixed version](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#known-issues-for-fixed-version) +- [The path of fixed version of the WebView2 Runtime should not contain \Edge\Application\.](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.1245.22#createcorewebview2environmentwithoptions) + +Name: WebviewBrowserPath
Type: `string` + +#### Theme + +Minimum Windows Version: Windows 10 2004/20H1 + +This defines the theme that the application should use: + +| Value | Description | +| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| SystemDefault | _Default_. The theme will be based on the system default. If the user changes their theme, the application will update to use the new setting | +| Dark | The application will use a dark theme exclusively | +| Light | The application will use a light theme exclusively | + +Name: Theme
Type: `windows.Theme` + +#### CustomTheme + +:::note + +Minimum Windows Version: Windows 10/11 2009/21H2 Build 22000 + +::: + +Allows you to specify custom colours for TitleBar, TitleText and Border for both light and dark mode, as well as when the window is active or inactive. + +Name: CustomTheme
Type: `windows.CustomTheme` + +##### CustomTheme type + +The CustomTheme struct uses `int32` to specify the colour values. These are in the standard(!) Windows format of: `0x00BBGGAA`. A helper function is provided to do RGB conversions into this format: `windows.RGB(r,g,b uint8)`. + +NOTE: Any value not provided will default to black. + +```go +type ThemeSettings struct { + DarkModeTitleBar int32 + DarkModeTitleBarInactive int32 + DarkModeTitleText int32 + DarkModeTitleTextInactive int32 + DarkModeBorder int32 + DarkModeBorderInactive int32 + LightModeTitleBar int32 + LightModeTitleBarInactive int32 + LightModeTitleText int32 + LightModeTitleTextInactive int32 + LightModeBorder int32 + LightModeBorderInactive int32 +} +``` + +Example: + +```go + CustomTheme: &windows.ThemeSettings{ + // Theme to use when window is active + DarkModeTitleBar: windows.RGB(255, 0, 0), // Red + DarkModeTitleText: windows.RGB(0, 255, 0), // Green + DarkModeBorder: windows.RGB(0, 0, 255), // Blue + LightModeTitleBar: windows.RGB(200, 200, 200), + LightModeTitleText: windows.RGB(20, 20, 20), + LightModeBorder: windows.RGB(200, 200, 200), + // Theme to use when window is inactive + DarkModeTitleBarInactive: windows.RGB(128, 0, 0), + DarkModeTitleTextInactive: windows.RGB(0, 128, 0), + DarkModeBorderInactive: windows.RGB(0, 0, 128), + LightModeTitleBarInactive: windows.RGB(100, 100, 100), + LightModeTitleTextInactive: windows.RGB(10, 10, 10), + LightModeBorderInactive: windows.RGB(100, 100, 100), + }, +``` + +#### Messages + +A struct of strings used by the webview2 installer if a valid webview2 runtime is not found. + +Name: Messages
Type: `*windows.Messages` + +Customise this for any language you choose to support. + +#### ResizeDebounceMS + +ResizeDebounceMS is the amount of time to debounce redraws of webview2 when resizing the window. The default value (0) will perform redraws as fast as it can. + +Name: ResizeDebounceMS
Type: `uint16` + +#### OnSuspend + +If set, this function will be called when Windows initiates a switch to low power mode (suspend/hibernate) + +Name: OnSuspend
Type: `func()` + +#### OnResume + +If set, this function will be called when Windows resumes from low power mode (suspend/hibernate) + +Name: OnResume
Type: `func()` + +#### WebviewGpuIsDisabled + +Setting this to `true` will disable GPU hardware acceleration for the webview. + +Name: WebviewGpuIsDisabled
Type: `bool` + +#### EnableSwipeGestures + +Setting this to `true` will enable swipe gestures for the webview. + +Name: EnableSwipeGestures
Type: `bool` + +### Mac + +This defines [Mac specific options](#mac). + +Name: Mac
Type: `*mac.Options` + +#### TitleBar + +The TitleBar struct provides the ability to configure the look and feel of the title bar. + +Name: TitleBar
Type: [`*mac.TitleBar`](#titlebar-struct) + +##### Titlebar struct + +The titlebar of the application can be customised by using the TitleBar options: + +```go +type TitleBar struct { + TitlebarAppearsTransparent bool + HideTitle bool + HideTitleBar bool + FullSizeContent bool + UseToolbar bool + HideToolbarSeparator bool +} +``` + +| Name | Description | +| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| TitlebarAppearsTransparent | Makes the titlebar transparent. This has the effect of hiding the titlebar and the content fill the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindow/1419167-titlebarappearstransparent?language=objc) | +| HideTitle | Hides the title of the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindowtitlevisibility?language=objc) | +| HideTitleBar | Removes [NSWindowStyleMaskTitled](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemasktitled/) from the style mask | +| FullSizeContent | Makes the webview fill the entire window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemaskfullsizecontentview) | +| UseToolbar | Adds a default toolbar to the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nstoolbar?language=objc) | +| HideToolbarSeparator | Removes the line beneath the toolbar. [Apple Docs](https://developer.apple.com/documentation/appkit/nstoolbar/1516954-showsbaselineseparator?language=objc) | + +Preconfigured titlebar settings are available: + +| Setting | Example | +| --------------------------- | ---------------------------------------------- | +| `mac.TitleBarDefault()` | ![](/img/reference/titlebar-default.webp) | +| `mac.TitleBarHidden()` | ![](/img/reference/titlebar-hidden.webp) | +| `mac.TitleBarHiddenInset()` | ![](/img/reference/titlebar-hidden-inset.webp) | + +Example: + +```go +Mac: &mac.Options{ + TitleBar: mac.TitleBarHiddenInset(), +} +``` + +Click [here](https://github.com/lukakerr/NSWindowStyles) for some inspiration on customising the titlebar. + +#### Appearance + +Appearance is used to set the style of your app in accordance with Apple's [NSAppearance](https://developer.apple.com/documentation/appkit/nsappearancename?language=objc) names. + +Name: Appearance
Type: [`mac.AppearanceType`](#appearance-type) + +##### Appearance type + +You can specify the application's [appearance](https://developer.apple.com/documentation/appkit/nsappearance?language=objc). + +| Value | Description | +| ----------------------------------------------------- | --------------------------------------------------------------- | +| DefaultAppearance | DefaultAppearance uses the default system value | +| NSAppearanceNameAqua | The standard light system appearance | +| NSAppearanceNameDarkAqua | The standard dark system appearance | +| NSAppearanceNameVibrantLight | The light vibrant appearance | +| NSAppearanceNameAccessibilityHighContrastAqua | A high-contrast version of the standard light system appearance | +| NSAppearanceNameAccessibilityHighContrastDarkAqua | A high-contrast version of the standard dark system appearance | +| NSAppearanceNameAccessibilityHighContrastVibrantLight | A high-contrast version of the light vibrant appearance | +| NSAppearanceNameAccessibilityHighContrastVibrantDark | A high-contrast version of the dark vibrant appearance | + +Example: + +```go +Mac: &mac.Options{ + Appearance: mac.NSAppearanceNameDarkAqua, +} +``` + +#### WebviewIsTransparent + +Setting this to `true` will make the webview background transparent when an alpha value of `0` is used. This means that if you use `rgba(0,0,0,0)` for `background-color` in your CSS, the host window will show through. Often combined with [WindowIsTranslucent](#WindowIsTranslucent) to make frosty-looking applications. + +Name: WebviewIsTransparent
Type: `bool` + +#### WindowIsTranslucent + +Setting this to `true` will make the window background translucent. Often combined with [WebviewIsTransparent](#WebviewIsTransparent) to make frosty-looking applications. + +Name: WindowIsTranslucent
Type: `bool` + +#### Preferences + +The Preferences struct provides the ability to configure the Webview preferences. + +Name: Preferences
Type: [`*mac.Preferences`](#preferences-struct) + +##### Preferences struct + +You can specify the webview preferences. + +```go +type Preferences struct { + TabFocusesLinks u.Bool + TextInteractionEnabled u.Bool + FullscreenEnabled u.Bool +} +``` + +| Name | Description | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| TabFocusesLinks | A Boolean value that indicates whether pressing the tab key changes the focus to links and form controls. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/2818595-tabfocuseslinks?language=objc) | +| TextInteractionEnabled | A Boolean value that indicates whether to allow people to select or otherwise interact with text. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3727362-textinteractionenabled?language=objc) | +| FullscreenEnabled | A Boolean value that indicates whether a web view can display content full screen. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3917769-elementfullscreenenabled?language=objc) | + +Example: + +```go +Mac: &mac.Options{ + Preferences: &mac.Preferences{ + TabFocusesLinks: mac.Enabled, + TextInteractionEnabled: mac.Disabled, + FullscreenEnabled: mac.Enabled, + } +} +``` + +#### About + +This configuration lets you set the title, message and icon for the "About" menu item in the app menu created by the "AppMenu" role. + +Name: About
Type: [`*mac.AboutInfo`](#about-struct) + +##### About struct + +```go + +type AboutInfo struct { + Title string + Message string + Icon []byte +} +``` + +If these settings are provided, an "About" menu item will appear in the app menu (when using the `AppMenu` role). Given this configuration: + +```go +//go:embed build/appicon.png +var icon []byte + +func main() { + err := wails.Run(&options.App{ + ... + Mac: &mac.Options{ + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + }) +``` + +The "About" menu item will appear in the app menu: + +```mdx-code-block +
+ +
+
+``` + +When clicked, that will open an about message box: + +```mdx-code-block +
+ +
+
+``` + +### Linux + +This defines [Linux specific options](#linux). + +Name: Linux
Type: `*linux.Options` + +#### Icon + +Sets up the icon representing the window. This icon is used when the window is minimized (also known as iconified). + +Name: Icon
Type: `[]byte` + +Some window managers or desktop environments may also place it in the window frame, or display it in other contexts. On others, the icon is not used at all, so your mileage may vary. + +NOTE: Gnome on Wayland at least does not display this icon. To have a application icon there, a `.desktop` file has to be used. On KDE it should work. + +The icon should be provided in whatever size it was naturally drawn; that is, don’t scale the image before passing it. Scaling is postponed until the last minute, when the desired final size is known, to allow best quality. + +#### WindowIsTranslucent + +Setting this to `true` will make the window background translucent. Some window managers may ignore it, or result in a black window. + +Name: WindowIsTranslucent
Type: `bool` + +#### WebviewGpuPolicy + +This option is used for determining the webview's hardware acceleration policy. + +Name: WebviewGpuPolicy
Type: [`options.WebviewGpuPolicy`](#webviewgpupolicy-type)
Default: `WebviewGpuPolicyAlways` + +##### WebviewGpuPolicy type + +| Value | Description | +| ------------------------ | -------------------------------------------------------------------- | +| WebviewGpuPolicyAlways | Hardware acceleration is always enabled | +| WebviewGpuPolicyOnDemand | Hardware acceleration is enabled/disabled as request by web contents | +| WebviewGpuPolicyNever | Hardware acceleration is always disabled | + +#### ProgramName + +This option is used to set the program's name for the window manager via GTK's g_set_prgname(). This name should not be localized, [see the docs](https://docs.gtk.org/glib/func.set_prgname.html). + +When a .desktop file is created this value helps with window grouping and desktop icons when the .desktop file's `Name` property differs form the executable's filename. + +Name: ProgramName
Type: string
+ +### Debug + +This defines [Debug specific options](#Debug) that apply to debug builds. + +Name: Debug
Type: `options.Debug` + +#### OpenInspectorOnStartup + +Setting this to `true` will open the WebInspector on startup of the application. + +Name: OpenInspectorOnStartup
Type: `bool` + +[^1]: This requires WebKit2GTK 2.36+ support and your app needs to be build with the build tag `webkit2_36` to activate support for this feature. This also bumps the minimum requirement of WebKit2GTK to 2.36 for your app. +[^2]: This requires WebKit2GTK 2.40+ support and your app needs to be build with the build tag `webkit2_40` to activate support for this feature. This also bumps the minimum requirement of WebKit2GTK to 2.40 for your app. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx new file mode 100644 index 00000000000..8e763502bcc --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx @@ -0,0 +1,92 @@ +--- +sidebar_position: 5 +--- + +# Project Config + +The project config resides in the `wails.json` file in the project directory. The structure of the config is: + +```json5 +{ + // Project config version + "version": "", + // The project name + "name": "", + // Relative path to the directory containing the compiled assets, this is normally inferred and could be left empty + "assetdir": "", + // Additional directories to trigger reloads (comma separated), this is only used for some advanced asset configurations + "reloaddirs": "", + // The directory where the build files reside. Defaults to 'build' + "build:dir": "", + // Relative path to the frontend directory. Defaults to 'frontend' + "frontend:dir": "", + // The command to install node dependencies, run in the frontend directory - often `npm install` + "frontend:install": "", + // The command to build the assets, run in the frontend directory - often `npm run build` + "frontend:build": "", + // This command has been replaced by frontend:dev:build. If frontend:dev:build is not specified will falls back to this command. \nIf this command is also not specified will falls back to frontend:build + "frontend:dev": "", + // This command is the dev equivalent of frontend:build. If not specified falls back to frontend:dev + "frontend:dev:build": "", + // This command is the dev equivalent of frontend:install. If not specified falls back to frontend:install + "frontend:dev:install": "", + // This command is run in a separate process on `wails dev`. Useful for 3rd party watchers or starting 3d party dev servers + "frontend:dev:watcher": "", + // URL to a 3rd party dev server to be used to serve assets, EG Vite. \nIf this is set to 'auto' then the devServerUrl will be inferred from the Vite output + "frontend:dev:serverUrl": "", + // Relative path to the directory that the auto-generated JS modules will be created + "wailsjsdir": "", + // The name of the binary + "outputfilename": "", + // The default time the dev server waits to reload when it detects a change in assets + "debounceMS": 100, + // Address to bind the wails dev sever to. Default: localhost:34115 + "devServer": "", + // Arguments passed to the application in shell style when in dev mode + "appargs": "", + // Defines if build hooks should be run though they are defined for an OS other than the host OS. + "runNonNativeBuildHooks": false, + "preBuildHooks": { + // The command that will be executed before a build of the specified GOOS/GOARCH: ${platform} is replaced with the "GOOS/GOARCH". The "GOOS/GOARCH" hook is executed before the "GOOS/*" and "*/*" hook. + "GOOS/GOARCH": "", + // The command that will be executed before a build of the specified GOOS: ${platform} is replaced with the "GOOS/GOARCH". The "GOOS/*" hook is executed before the "*/*" hook. + "GOOS/*": "", + // The command that will be executed before every build: ${platform} is replaced with the "GOOS/GOARCH". + "*/*": "" + }, + "postBuildHooks": { + // The command that will be executed after a build of the specified GOOS/GOARCH: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. The "GOOS/GOARCH" hook is executed before the "GOOS/*" and "*/*" hook. + "GOOS/GOARCH": "", + // The command that will be executed after a build of the specified GOOS: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. The "GOOS/*" hook is executed before the "*/*" hook. + "GOOS/*": "", + // The command that will be executed after every build: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. + "*/*": "" + }, + // Data used to populate manifests and version info. + "info": { + // The company name. Default: [The project name] + "companyName": "", + // The product name. Default: [The project name] + "productName": "", + // The version of the product. Default: '1.0.0' + "productVersion": "", + // The copyright of the product. Default: 'Copyright.........' + "copyright": "", + // A short comment of the app. Default: 'Built using Wails (https://wails.app)' + "comments": "" + }, + // 'multiple': One installer per architecture. 'single': Single universal installer for all architectures being built. Default: 'multiple' + "nsisType": "", + // Whether the app should be obfuscated. Default: false + "obfuscated": "", + // The arguments to pass to the garble command when using the obfuscated flag + "garbleargs": "" +} +``` + +This file is read by the Wails CLI when running `wails build` or `wails dev`. + +The `assetdir`, `reloaddirs`, `wailsjsdir`, `debounceMS`, `devserver` and `frontenddevserverurl` flags in `wails build/dev` will update the project config +and thus become defaults for subsequent runs. + +The JSON Schema for this file is located [here](https://wails.io/schemas/config.v2.json). diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx new file mode 100644 index 00000000000..2765c844d53 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx @@ -0,0 +1,13 @@ +--- +sidebar_position: 7 +--- + +# Browser + +Esses métodos estão relacionados com o navegador do sistema. + +### BrowserOpenURL + +Abre a URL fornecida no navegador do sistema. + +Go: `BrowserOpenURL(ctx context.Context, url string)`
JS: `BrowserOpenURL(url string)` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx new file mode 100644 index 00000000000..805f68ed917 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx @@ -0,0 +1,23 @@ +--- +sidebar_position: 8 +--- + +# Clipboard + +This part of the runtime provides access to the operating system's clipboard.
The current implementation only handles text. + +### ClipboardGetText + +This method reads the currently stored text from the clipboard. + +Go: `ClipboardGetText(ctx context.Context) (string, error)`
Returns: a string (if the clipboard is empty an empty string will be returned) or an error. + +JS: `ClipboardGetText(): Promise`
Returns: a promise with a string result (if the clipboard is empty an empty string will be returned). + +### ClipboardSetText + +This method writes a text to the clipboard. + +Go: `ClipboardSetText(ctx context.Context, text string) error`
Returns: an error if there is any. + +JS: `ClipboardSetText(text: string): Promise`
Returns: a promise with true result if the text was successfully set on the clipboard, false otherwise. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx new file mode 100644 index 00000000000..6a12ce1350a --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx @@ -0,0 +1,302 @@ +--- +sidebar_position: 5 +--- + +# Diálogo + +Esta parte do tempo de execução fornece acesso a dialogos nativos, como os Seletores de Arquivo e caixas de mensagem. + +:::info JavaScript + +O dialog não é suportado pelo runtime do JS. + +::: + +### OpenDirectoryDialog + +Abre um diálogo que solicita o usuário para selecionar um diretório. Pode ser personalizado usando o [OpenDialogOptions](#opendialogoptions). + +Go: `OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)` + +Retorna: Diretório selecionado (nulo se o usuário cancelar) ou um erro + +### OpenFileDialog + +Abre um diálogo que solicita o usuário para selecionar um arquivo. Pode ser personalizado usando o [OpenDialogOptions](#opendialogoptions). + +Go: `OpenFileDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)` + +Retorna: Arquivo selecionado (nulo se o usuário cancelar) ou um erro + +### OpenMultipleFilesDialog + +Abre um diálogo que pede o usuário para selecionar vários arquivos. Pode ser personalizado usando o [OpenDialogOptions](#opendialogoptions). + +Go: `OpenMultipleFilesDialog(ctx context.Context, dialogOptions OpenDialogOptions) ([]string, error)` + +Retorna: Arquivos selecionados (nulo se o usuário cancelar) ou um erro + +### SaveFileDialog + +Abre um diálogo que solicita o usuário selecionar um nome de arquivo para salvar. Pode ser personalizado usando [SaveDialogOptions](#savedialogoptions). + +Go: `SaveFileDialog(ctx context.Context, dialogOptions SaveDialogOptions) (string, error)` + +Retorna: O arquivo selecionado (nulo se o usuário cancelar) ou um erro + +### MessageDialog + +Exibe uma mensagem usando a caixa de diálogo da mensagem. Pode ser personalizado usando o [MessageDialogOptions](#messagedialogoptions). + +Go: `MessageDialog(ctx context.Context, dialogOptions MessageDialogOptions) (string, error)` + +Retorna: O texto do botão selecionado ou um erro + +## Opções + +### OpenDialogOptions + +```go +type OpenDialogOptions struct { + DefaultDirectory string + DefaultFilename string + Title string + Filters []FileFilter + ShowHiddenFiles bool + CanCreateDirectories bool + ResolvesAliases bool + TreatPackagesAsDirectories bool +} +``` + +| Atributo | Descrição | Win | Mac | Lin | +| -------------------------- | ------------------------------------------------------------- | --- | --- | --- | +| DefaultDirectory | O diretório que a caixa de diálogo será exibida quando aberta | ✅ | ✅ | ✅ | +| DefaultFilename | O nome do arquivo padrão | ✅ | ✅ | ✅ | +| Title | Título para a caixa de diálogo | ✅ | ✅ | ✅ | +| [Filters](#filefilter) | Uma lista de filtros de arquivos | ✅ | ✅ | ✅ | +| ShowHiddenFiles | Exibir arquivos ocultos pelo sistema | | ✅ | ✅ | +| CanCreateDirectories | Permitir que o usuário crie diretórios | | ✅ | | +| ResolvesAliases | Se verdadeiro, retorna o arquivo não o alias | | ✅ | | +| TreatPackagesAsDirectories | Permitir a navegação em pacotes | | ✅ | | + +### SaveDialogOptions + +```go +type SaveDialogOptions struct { + DefaultDirectory string + DefaultFilename string + Title string + Filters []FileFilter + ShowHiddenFiles bool + CanCreateDirectories bool + TreatPackagesAsDirectories bool +} +``` + +| Atributo | Descrição | Win | Mac | Lin | +| -------------------------- | ------------------------------------------------------------- | --- | --- | --- | +| DefaultDirectory | O diretório que a caixa de diálogo será exibida quando aberta | ✅ | ✅ | ✅ | +| DefaultFilename | O nome do arquivo padrão | ✅ | ✅ | ✅ | +| Title | Título para a caixa de diálogo | ✅ | ✅ | ✅ | +| [Filters](#filefilter) | Uma lista de filtros de arquivos | ✅ | ✅ | ✅ | +| ShowHiddenFiles | Exibir arquivos ocultos pelo sistema | | ✅ | ✅ | +| CanCreateDirectories | Permitir que o usuário crie diretórios | | ✅ | | +| TreatPackagesAsDirectories | Permitir a navegação em pacotes | | ✅ | | + +### MessageDialogOptions + +```go +type MessageDialogOptions struct { + Type DialogType + Title string + Message string + Buttons []string + DefaultButton string + CancelButton string +} +``` + +| Atributo | Descrição | Win | Mac | Lin | +| ------------- | ------------------------------------------------------------------------ | -------------- | --- | --- | +| Tipo | O tipo de diálogo de mensagem, por exemplo, pergunta, informações... | ✅ | ✅ | ✅ | +| Title | Título para a caixa de diálogo | ✅ | ✅ | ✅ | +| Message | A mensagem para mostrar o usuário | ✅ | ✅ | ✅ | +| Buttons | Uma lista de títulos de botões | | ✅ | | +| DefaultButton | O botão com este texto deve ser tratado como padrão. Vincule a `return`. | ✅[*](#windows) | ✅ | | +| CancelButton | O botão com este texto deve ser tratado como padrão. Vincule a `return` | | ✅ | | + +#### Windows + +Windows tem tipos de diálogo padrão em que os botões não são personalizáveis. O valor retornado será um dos: "Ok", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No", "Try Again" or "Continue". + +Para diálogos de Perguntas, o botão padrão é "Sim" e o botão cancelar é "Não". Isso pode ser alterado definindo o valor do `DefaultButton` para `"No"`. + +Exemplo: +```go + result, err := runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Question", + Message: "Do you want to continue?", + DefaultButton: "No", + }) +``` + +#### Linux + +Linux tem tipos de diálogo padrão em que os botões não são personalizáveis. O valor retornado será um de: "Ok", "Cancel", "Yes", "No" + +#### Mac + +Uma caixa de diálogo de mensagem no Mac pode especificar até 4 botões. Se nenhum `DefaultButton` ou `CancelButton` for dado, o primeiro botão é considerado padrão e está ligado à chave `return`. + +Para o código a seguir: + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, +}) +``` + +o primeiro botão é mostrado como padrão: + +```mdx-code-block +
+ +
+
+``` + +E se especificarmos o `DefaultButton` como "two": + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, + DefaultButton: "two", +}) +``` + +o segundo botão será mostrado como padrão. Quando `return` é pressionado, o valor "dois" é retornado. + +```mdx-code-block +
+ +
+
+``` + +Se especificarmos agora o `CancelButton` como "três: + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, + DefaultButton: "two", + CancelButton: "three", +}) +``` + +o botão com "três" é mostrado na parte inferior do diálogo. Quando `escape` é pressionado, o valor "três" é retornado: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### DialogType + +```go +const ( + InfoDialog DialogType = "info" + WarningDialog DialogType = "warning" + ErrorDialog DialogType = "error" + QuestionDialog DialogType = "question" + ) +``` + +### FileFilter + +```go +type FileFilter struct { + DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)" + Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png" +} +``` + +#### Windows + +O Windows permite que você use vários filtros de arquivos em caixas de diálogo. Cada FileFilter aparecerá como uma entrada separada na caixa de diálogo: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### Linux + +Linux permite que você use vários filtros de arquivo em caixas de diálogo. Cada FileFilter aparecerá como uma entrada separada na caixa de diálogo: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### Mac + +As caixas de diálogo Mac possuem apenas o conceito de um único conjunto de padrões para filtrar arquivos. Se vários Filtros forem fornecidos, o Wails usará todos os padrões definidos. + +Exemplo: + +```go + selection, err := runtime.OpenFileDialog(b.ctx, runtime.OpenDialogOptions{ + Title: "Select File", + Filters: []runtime.FileFilter{ + { + DisplayName: "Images (*.png;*.jpg)", + Pattern: "*.png;*.jpg", + }, { + DisplayName: "Videos (*.mov;*.mp4)", + Pattern: "*.mov;*.mp4", + }, + }, + }) +``` + +Isso resultará na caixa de diálogo Abrir Arquivo usando `*.png,*.jpg,*.mov,*.mp4` como filtro. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx new file mode 100644 index 00000000000..ec0eb61e4e7 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx @@ -0,0 +1,37 @@ +--- +sidebar_position: 2 +--- + +# Events + +The Wails runtime provides a unified events system, where events can be emitted or received by either Go or JavaScript. Opcionalmente, dados podem ser passados com os eventos. Os ouvintes receberão os dados nos tipos de dados locais. + +### EventsOn + +Este método configura um ouvinte para o nome do evento. Quando um evento do tipo `eventName` é [emitted](#EventsEmit), a callback é acionada. Quaisquer dados adicionais enviados com o evento emitido serão passados para o retorno de chamada. Retorna uma função para cancelar o ouvinte. + +Go: `EventsOn(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`
JS: `EventsOn(eventName string, callback function(optionalData?: any)): () => void` + +### EventsOff + +Este método desregistra o listener para o nome do evento, opcionalmente várias listagens podem ser desregistradas via `adicionalEventNames`. + +Go: `EventsOff(ctx context.Context, eventName string, additionalEventNames ...string)`
JS: `EventsOff(eventName string, ...additionalEventNames)` + +### EventsOnce + +Esse método configura um listener para o nome do evento, mas só será acionado uma vez. Retorna uma função para cancelar o ouvinte. + +Go: `EventsOnce(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`
JS: `EventsOnce(eventName string, callback function(optionalData?: any)): () => void` + +### EventsOnMultiple + +Este método configura um listener para o nome do evento, mas acionará apenas um máximo de `counter` vezes. Retorna uma função para cancelar o ouvinte. + +Go: `EventsOnMultiple(ctx context.Context, eventName string, callback func(optionalData ...interface{}), counter int) func()`
JS: `EventsOnMultiple(eventName string, callback function(optionalData?: any), counter int): () => void` + +### EventsEmit + +Este método emite o evento fornecido. Os dados opcionais podem ser passados com o evento. Isto irá acionar quaisquer ouvintes de eventos. + +Go: `EventsEmit(ctx context.Context, eventName string, optionalData ...interface{})`
JS: `EventsEmit(eventName: string, ...optionalData: any)` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx new file mode 100644 index 00000000000..b6f4e8a787c --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx @@ -0,0 +1,85 @@ +--- +sidebar_position: 1 +--- + +# Introduction + +O runtime é uma biblioteca que fornece métodos utilitários para sua aplicação. There is both a Go and JavaScript runtime and the aim is to try and keep them at parity where possible. + +Ele tem métodos de utilitário para: + +- [Janelas](window.mdx) +- [Menus](menu.mdx) +- [Caixa de diálogo](dialog.mdx) +- [Eventos](events.mdx) +- [Browser](browser.mdx) +- [Registro](log.mdx) +- [Clipboard](clipboard.mdx) + +O runtime do Go está disponível através da importação de `github.com/wailsapp/wails/v2/pkg/runtime`. Todos os métodos neste pacote assumem um contexto como o primeiro parâmetro. Este contexto deve ser obtido a partir dos ganchos [OnStartup](../options.mdx#onstartup) ou [OnDomReady](../options.mdx#ondomready). + +:::info Nota + +Embora o contexto seja fornecido para o método [Inicialização](../options.mdx#onstartup), não há garantia de que o runtime funcionará neste método, pois a janela está inicializando em um tópico diferente. Se você deseja chamar métodos de tempo de execução na inicialização, use [OnDomReady](../options.mdx#ondomready). + +::: + +The JavaScript library is available to the frontend via the `window.runtime` map. There is a runtime package generated when using `dev` mode that provides TypeScript declarations for the runtime. Isso deve ser localizado no diretório `wailsjs` em seu diretório frontend. + +### Hide + +Go: `Hide(ctx context.Context)`
JS: `Hide()` + +Oculta a aplicação. + +:::info Nota + +No Mac, isto irá ocultar o aplicativo da mesma forma que o `Ocultar` item de menu nos aplicativos padrão Mac. Isso é diferente de esconder a janela, mas a aplicação ainda está em primeiro plano. Para Windows e Linux, atualmente isso é o mesmo que `WindowHide`. + +::: + +### Show + +Mostra a aplicação. + +:::info Nota + +No Mac, a aplicação voltará a ser apresentada em primeiro plano. Para Windows e Linux, atualmente isso é o mesmo que `WindowShow`. + +::: + +Go: `Show(ctx context.Context)`
JS: `Show()` + +### Quit + +Encerra a aplicação. + +Go: `Quit(ctx context.Context)`
JS: `Quit()` + +### Environment + +Retorna detalhes do ambiente atual. + +Go: `Environment(ctx context.Context) EnvironmentInfo`
JS: `Environment(): Promise` + +#### EnvironmentInfo + +Go: + +```go +type EnvironmentInfo struct { + BuildType string + Platform string + Arch string +} +``` + +JS: + +```ts +interface EnvironmentInfo { + buildType: string; + platform: string; + arch: string; +} +``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx new file mode 100644 index 00000000000..0513b9431fd --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 3 +--- + +# Registro + +The Wails runtime provides a logging mechanism that may be called from Go or JavaScript. Como a maioria dos registros de, há um número de níveis de log: + +- Trace +- Debug +- Info +- Warning +- Error +- Fatal + +O logger irá gerar qualquer mensagem de log no nível atual, ou superior, de log. Exemplo: O `Debug` log level irá retornar todas as mensagens exceto `Trace` mensagens. + +### LogPrint + +Registra a mensagem dada como uma mensagem "bruta". + +Go: `LogPrint(ctx context.Context, message string)`
JS: `LogPrint(message: string)` + +### LogPrintf + +Registra a mensagem dada como uma mensagem "bruta". + +Go: `LogPrintf(ctx context.Context, format string, args ...interface{})`
+ +### LogTrace + +Registra a mensagem dada no `nível de log`. + +Go: `LogTrace(ctx context.Context, message string)`
JS: `LogTrace(message: string)` + +### LogTracef + +Registra a mensagem dada no `nível de log`. + +Go: `LogTracef(ctx context.Context, format string, args ...interface{})`
+ +### LogDebug + +Registra a mensagem dada no nível de log `Debug`. + +Go: `LogDebug(ctx context.Context, message string)`
JS: `LogDebug(message: string)` + +### LogDebugf + +Registra a mensagem dada no nível de log `Debug`. + +Go: `LogDebugf(ctx context.Context, format string, args ...interface{})`
+ +### LogInfo + +Registra a mensagem dada no nível de log de `Info`. + +Go: `LogInfo(ctx context.Context, message string)`
JS: `LogInfo(message: string)` + +### LogInfof + +Registra a mensagem dada no nível de log de `Info`. + +Go: `LogInfof(ctx context.Context, format string, args ...interface{})`
+ +### LogWarning + +Registra a mensagem dada no nível de log de `Warning`. + +Go: `LogWarning(ctx context.Context, message string)`
JS: `LogWarning(message: string)` + +### LogWarningf + +Registra a mensagem dada no nível de log de `Warning`. + +Go: `LogWarningf(ctx context.Context, format string, args ...interface{})`
+ +### LogError + +Registra a mensagem dada no nível de log de `Error`. + +Go: `LogError(ctx context.Context, message string)`
JS: `LogError(message: string)` + +### LogErrorf + +Registra a mensagem dada no nível de log de `Error`. + +Go: `LogErrorf(ctx context.Context, format string, args ...interface{})`
+ +### LogFatal + +Registra a mensagem dada no nível de log `Fatal`. + +Go: `LogFatal(ctx context.Context, message string)`
JS: `LogFatal(message: string)` + +### LogFatalf + +Registra a mensagem dada no nível de log `Fatal`. + +Go: `LogFatalf(ctx context.Context, format string, args ...interface{})`
+ +### LogSetLogLevel + +Define o nível de log. In JavaScript, the number relates to the following log levels: + +| Valor | Nível de Log | +| ----- | ------------ | +| 1 | Trace | +| 2 | Debug | +| 3 | Info | +| 4 | Warning | +| 5 | Erro | + +Go: `LogSetLogLevel(ctx context.Context, level logger.LogLevel)`
JS: `LogSetLogLevel(level: number)` + +## Usando um Logger personalizado + +Um logger personalizado pode ser usado fornecendo usando a opção de aplicativo [Logger](../options.mdx#logger). O único requisito é que o logger implemente a interface de `logger.Logger` definida em `github.com/wailsapp/wails/v2/pkg/logger`: + +```go title="logger.go" +type Logger interface { + Print(message string) + Trace(message string) + Debug(message string) + Info(message string) + Warning(message string) + Error(message string) + Fatal(message string) +} +``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx new file mode 100644 index 00000000000..ae07d327c93 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx @@ -0,0 +1,25 @@ +--- +sidebar_position: 6 +--- + +# Menus + +Estes métodos estão relacionados ao menu da aplicação. + +:::info JavaScript + +O menu não é suportado atualmente no runtime do JS. + +::: + +### MenuSetApplicationMenu + +Define o menu do aplicativo para o [menu](../menus.mdx) fornecido. + +Go: `MenuSetApplicationMenu(ctx context.Context, menu *menu.Menu)` + +### MenuUpdateApplicationMenu + +Atualiza o menu do aplicativo, pegando qualquer alteração no menu passado para `MenuSetApplicationMenu`. + +Go: `MenuUpdateApplicationMenu(ctx context.Context)` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx new file mode 100644 index 00000000000..457c92ebff9 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx @@ -0,0 +1,38 @@ +--- +sidebar_position: 9 +--- + +# Screen + +These methods provide information about the currently connected screens. + +### ScreenGetAll + +Returns a list of currently connected screens. + +Go: `ScreenGetAll(ctx context.Context) []screen`
+JS: `ScreenGetAll()` + +#### Screen + +Go struct: + +```go +type Screen struct { + IsCurrent bool + IsPrimary bool + Width int + Height int +} +``` + +Typescript interface: + +```ts +interface Screen { + isCurrent: boolean; + isPrimary: boolean; + width : number + height : number +} +``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx new file mode 100644 index 00000000000..04cc08ea679 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx @@ -0,0 +1,227 @@ +--- +sidebar_position: 4 +--- + +# Janela + +Esses métodos dão controle da janela do aplicativo. + +### WindowSetTitle + +Define o texto na barra de título da janela. + +Go: `WindowSetTitle(ctx context.Context, title string)`
JS: `WindowSetTitle(title: string)` + +### WindowFullscreen + +Faz a janela estar em tela cheia. + +Go: `WindowFullscreen(ctx context.Context)`
JS: `WindowFullscreen()` + +### WindowUnfullscreen + +Restaura as dimensões e a posição anteriores da janela antes da tela cheia. + +Go: `WindowUnfullscreen(ctx context.Context)`
JS: `WindowUnfullscreen()` + +### WindowIsFullscreen + +Retorna verdadeiro se a janela estiver em tela cheia. + +Go: `WindowIsFullscreen(ctx context.Context) bool`
JS: `WindowIsFullscreen() bool` + +### WindowCenter + +Centraliza a janela no monitor que a janela está ativada. + +Go: `WindowCenter(ctx context.Context)`
JS: `WindowCenter()` + +### WindowExecJS + +Executa código JS arbitrário na janela. + +Este método executa o código no navegador de forma assíncrona e retorna imediatamente. Se o script causar quaisquer erros, eles só estarão disponíveis no console do navegador. + +Go: `WindowExecJS(ctx context.Context, js string)` + +### WindowReload + +Executa um "recarregar" (Recarrega a página atual). + +Go: `WindowReload(ctx context.Context)`
JS: `WindowReload()` + +### WindowReloadApp + +Recarrega o front-end do aplicativo. + +Go: `WindowReloadApp(ctx context.Context)`
JS: `WindowReloadApp()` + +### WindowSetSystemDefaultTheme + +Somente para Windows. + +Go: `WindowSetSystemDefaultTheme(ctx context.Context)`
JS: `WindowSetSystemDefaultTheme()` + +Define o tema da janela para padrão do sistema (escuro/claro). + +### WindowSetLightTheme + +Somente para Windows. + +Go: `WindowSetLightTheme(ctx context.Context)`
JS: `WindowSetLightTheme()` + +Define o tema da janela como claro. + +### WindowSetDarkTheme + +Somente para Windows. + +Go: `WindowSetDarkTheme(ctx context.Context)`
JS: `WindowSetDarkTheme()` + +Define o tema da janela como escuro. + +### WindowShow + +Mostra a janela, se ela estiver oculta no momento. + +Go: `WindowShow(ctx context.Context)`
JS: `WindowShow()` + +### WindowHide + +Oculta a janela, se ela estiver visível no momento. + +Go: `WindowHide(ctx context.Context)`
JS: `WindowHide()` + +### WindowIsNormal + +Retorna verdadeiro se a janela não for minimizada, maximizada ou tela inteira. + +Go: `WindowIsNormal(ctx context.Context) bool`
JS: `WindowIsNormal() bool` + +### WindowSetSize + +Define a largura e a altura da janela. + +Go: `WindowSetSize(ctx context.Context, width int, height int)`
JS: `WindowSetSize(width: number, height: number)` + +### WindowGetSize + +Obtém a largura e a altura da janela. + +Go: `WindowGetSize(ctx context.Context) (width int, height int)`
JS: `WindowGetSize() : Size` + +### WindowSetMinSize + +Define o tamanho mínimo da janela. Será redimensionada a janela se a janela for atualmente menor do que as dimensões fornecidas. + +Definir um tamanho de `0,0` irá desativar esta restrição. + +Go: `WindowSetMinSize(ctx context.Context, width int, height int)`
JS: `WindowSetMinSize(width: number, height: number)` + +### WindowSetMaxSize + +Define o tamanho máximo da janela. Será redimensionada a janela se a janela for atualmente maior do que as dimensões fornecidas. + +Definir um tamanho de `0,0` irá desativar esta restrição. + +Go: `WindowSetMaxSize(ctx context.Context, width int, height int)`
JS: `WindowSetMaxSize(width: number, height: number)` + +### WindowSetAlwaysOnTop + +Define a janela sempreOnTop ou não no topo. + +Go: `WindowSetAlwaysOnTop(ctx context.Context, b bool)`
JS: `WindowSetAlwaysOnTop(b: Boolen)` + +### WindowSetPosition + +Define a posição da janela em relação ao monitor da janela ativada. + +Go: `WindowSetPosition(ctx context.Context, x int, y int)`
JS: `WindowSetPosition(x: number, y: number)` + +### WindowGetPosition + +Obtém a posição da janela em relação ao monitor que a janela está ativada. + +Go: `WindowGetPosition(ctx context.Context) (x int, y int)`
JS: `WindowGetPosition() : Position` + +### WindowMaximise + +Maximiza a janela para preencher a tela. + +Go: `WindowMaximise(ctx context.Context)`
JS: `WindowMaximise()` + +### WindowUnmaximise + +Restaurar a janela para as dimensões e a posição antes de maximizar. + +Go: `WindowUnmaximise(ctx context.Context)`
JS: `WindowUnmaximise()` + +### WindowIsMaximised + +Retorna verdadeiro se a janela for maximizada. + +Go: `WindowIsMaximised(ctx context.Context) bool`
JS: `WindowIsMaximised() bool` + +### WindowToggleMaximise + +Alterna entre Maximizado e Não Maximizado. + +Go: `WindowToggleMaximise(ctx context.Context)`
JS: `WindowToggleMaximise()` + +### WindowMinimise + +Minimiza a janela. + +Go: `WindowMinimise(ctx context.Context)`
JS: `WindowMinimise()` + +### WindowUnminimise + +Restaura a janela para as dimensões e a posição antes de minimizar. + +Go: `WindowUnminimise(ctx context.Context)`
JS: `WindowUnminimise()` + +### WindowIsMinimised + +Retorna verdadeiro se a janela estiver minimizada. + +Go: `WindowIsMinimised(ctx context.Context) bool`
JS: `WindowIsMinimised() bool` + +### WindowSetBackgroundColour + +Define a cor de fundo da janela para a definição de cores RGBA fornecida. Esta cor será exibida para todos os pixels transparentes. + +Valores válidos para R, G, B e A são 0-255. + +:::info Windows + +No Windows, apenas valores alfa de 0 ou 255 são suportados. Qualquer valor que não for 0 será considerado 255. + +::: + +Go: `WindowSetBackgroundColour(ctx context.Context, R, G, B, A uint8)`
JS: `WindowSetBackgroundColour(R, G, B, A)` + +### WindowPrint + +Opens tha native print dialog. + +Go: `WindowPrint(ctx context.Context)`
JS: `WindowPrint()` + +## TypeScript Object Definitions + +### Position + +```ts +interface Position { + x: number; + y: number; +} +``` + +### Size + +```ts +interface Size { + w: number; + h: number; +} +``` diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx new file mode 100644 index 00000000000..1af16f7745a --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx @@ -0,0 +1,245 @@ +--- +sidebar_position: 20 +--- + +# Dogs API + +```mdx-code-block +
+ +
+
+``` + +:::note + +This tutorial has been kindly provided by [@tatadan](https://twitter.com/tatadan) and forms part of their [Wails Examples Repository](https://github.com/tataDan/wails-v2-examples). + +::: + +In this tutorial we are going to develop an application that retrieves photos of dogs from the web and then displays them. + +### Create the project + +Let's create the application. From a terminal enter: `wails init -n dogs-api -t svelte` + +Note: We could optionally add `-ide vscode` or `-ide goland` to the end of this command if you wanted to add IDE support. + +Now let's `cd dogs-api` and start editing the project files. + +### Remove unused code + +We will start by removing some elements that we know we will not use: + +- Open `app.go` and remove the following lines: + +```go +// Greet returns a greeting for the given name +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s, It's show time!", name) +} +``` + +- Open `frontend/src/App.svelte` and delete all lines. +- Delete the `frontend/src/assets/images/logo-universal.png` file + +### Creating our application + +Now let's add our new Go code. + +Add the following struct declarations to `app.go` before the function definitions: + +```go +type RandomImage struct { + Message string + Status string +} + +type AllBreeds struct { + Message map[string]map[string][]string + Status string +} + +type ImagesByBreed struct { + Message []string + Status string +} +``` + +Add the following functions to `app.go` (perhaps after the existing function definitions): + +```go +func (a *App) GetRandomImageUrl() string { + response, err := http.Get("https://dog.ceo/api/breeds/image/random") + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data RandomImage + json.Unmarshal(responseData, &data) + + return data.Message +} + +func (a *App) GetBreedList() []string { + var breeds []string + + response, err := http.Get("https://dog.ceo/api/breeds/list/all") + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data AllBreeds + json.Unmarshal(responseData, &data) + + for k := range data.Message { + breeds = append(breeds, k) + } + + sort.Strings(breeds) + + return breeds +} + +func (a *App) GetImageUrlsByBreed(breed string) []string { + + url := fmt.Sprintf("%s%s%s%s", "https://dog.ceo/api/", "breed/", breed, "/images") + response, err := http.Get(url) + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data ImagesByBreed + json.Unmarshal(responseData, &data) + + return data.Message +} +``` + +Modify the `import` section of `app.go` to look like this: + +```go +import ( + "context" + "fmt" + "encoding/json" + "io/ioutil" + "log" + "net/http" + "sort" +) +``` + +Add the following lines to `frontend/src/App.svelte`: + + +```html + + +

Dogs API

+
+ + Click on down arrow to select a breed + + +
+
+{#if showRandomPhoto} + No dog found +{/if} +{#if showBreedPhotos} + {#each photos as photo} + No dog found + {/each} +{/if} + + +``` + + +### Testing the application + +To generate the bindings and test the application, run `wails dev`. + +### Compiling the application + +To compile the application to a single, production grade binary, run `wails build`. diff --git a/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx new file mode 100644 index 00000000000..ea350890049 --- /dev/null +++ b/website/i18n/pt/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx @@ -0,0 +1,123 @@ +--- +sidebar_position: 10 +--- + +# Hello World + +The aim of this tutorial is to get you up and running with the most basic application using Wails. You will be able to: + +- Create a new Wails application +- Build the application +- Run the application + +:::note + +This tutorial uses Windows as the target platform. Output will vary slightly depending on your operating system. + +::: + +## Create a new Wails application + +To create a new Wails application using the default vanilla JS template, you need to run the following command: + +```bash +wails init -n helloworld +``` + +You should see something similar to the following: + +``` +Wails CLI v2.0.0 + +Initialising Project 'helloworld' +--------------------------------- + +Project Name: helloworld +Project Directory: C:\Users\leaan\tutorial\helloworld +Project Template: vanilla +Template Support: https://wails.io + +Initialised project 'helloworld' in 232ms. +``` + +This will create a new directory called `helloworld` in the current directory. In this directory, you will find a number of files: + +``` +build/ - Contains the build files + compiled application +frontend/ - Contains the frontend files +app.go - Contains the application code +main.go - The main program with the application configuration +wails.json - The project configuration file +go.mod - The go module file +go.sum - The go module checksum file +``` + +## Build the application + +To build the application, change to the new `helloworld` project directory and run the following command: + +```bash +wails build +``` + +You should see something like the following: + +``` +Wails CLI v2.0.0 + +App Type: desktop +Platforms: windows/amd64 +Compiler: C:\Users\leaan\go\go1.18.3\bin\go.exe +Build Mode: Production +Devtools: false +Skip Frontend: false +Compress: false +Package: true +Clean Build Dir: false +LDFlags: "" +Tags: [] +Race Detector: false + +Building target: windows/amd64 +------------------------------ + - Installing frontend dependencies: Done. + - Compiling frontend: Done. + - Generating bundle assets: Done. + - Compiling application: Done. +Built 'C:\Users\leaan\tutorial\helloworld\build\bin\helloworld.exe' in 10.616s. +``` + +This has compiled the application and saved it in the `build/bin` directory. + +## Run the application + +If we view the `build/bin` directory in Windows Explorer, we should see our project binary: + +```mdx-code-block +
+ +
+
+``` + +We can run it by simply double-clicking the `helloworld.exe` file. + +On Mac, Wails generates a `helloworld.app` file which can be run by double-clicking it. + +On Linux, you can run the application using `./helloworld` from the `build/bin` directory. + +You should see the application working as expected: + +```mdx-code-block +
+ +
+
+``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx new file mode 100644 index 00000000000..64c3f23b5ca --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 2 +--- + +# Ссылки + +Эта страница служит списком ссылок на сообщество. Пожалуйста, отправьте PR (нажмите `Редактировать эту страницу` внизу) для отправки ссылок. + +## Awesome Wails + +[Полный список](https://github.com/wailsapp/awesome-wails) ссылок, связанных с Wails. + +## Каналы поддержки + +- [Wails Discord Server](https://discord.gg/JDdSxwjhGf) +- [Github Issues](https://github.com/wailsapp/wails/issues) +- [v2 Beta Discussion Board](https://github.com/wailsapp/wails/discussions/828) + +## Социальные сети + +- [Twitter](https://twitter.com/wailsapp) +- [Wails группа в QQ китайского сообщества](https://qm.qq.com/cgi-bin/qm/qr?k=PmIURne5hFGNd7QWzW5qd6FV-INEjNJv&jump_from=webapi) - Номер группы: 1067173054 + +## Другие руководства и статьи + +- [Создание доски объявлений](https://blog.customct.com/building-bulletin-board) diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx new file mode 100644 index 00000000000..37be75135ed --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx @@ -0,0 +1,10 @@ +# BulletinBoard + +```mdx-code-block +

+ +
+

+``` + +The [BulletinBoard](https://github.com/raguay/BulletinBoard) application is a versital message board for static messages or dialogs to get information from the user for a script. It has a TUI for creating new dialogs that can latter be used to get information from the user. It's design is to stay running on your system and show the information as needed and then hide away. I have a process for watching a file on my system and sending the contents to BulletinBoard when changed. It works great with my workflows. There is also an [Alfred workflow](https://github.com/raguay/MyAlfred/blob/master/Alfred%205/EmailIt.alfredworkflow) for sending information to the program. The workflow is also for working with [EmailIt](https://github.com/raguay/EmailIt). diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..430f02c8327 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx @@ -0,0 +1,41 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) — отслеживайте +живые матчи любого профиля Street Fighter 6 или V CFN. Чтобы начать, посетите +[веб-сайт](https://cfn.williamsjokvist.se/). + +## Функции + +- Отслеживание матчей в режиме реального времени +- Хранение журналов матчей и статистики +- Поддержка отображения статистики в реальном времени в OBS через источник + браузера. +- Поддержка как SF6, так и SFV. +- Возможность для пользователей создавать свои собственные темы браузера OBS с + помощью CSS. + +### Основные технологии, используемые вместе с Wails + +- [Задача](https://github.com/go-task/task) - перенос Wails CLI для упрощения + использования общих команд. +- [React](https://github.com/facebook/react) — выбран из-за богатой экосистемы + (radix,framer-motion) +- [Bun](https://github.com/oven-sh/bun) – используется для быстрого разрешения + зависимостей и времени сборки. +- [Rod](https://github.com/go-rod/rod) – автономная автоматизация браузера для + аутентификации и опроса изменений. +- [SQLite](https://github.com/mattn/go-sqlite3) - используется для хранения + совпадений, сессий и профилей. +- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) + – http-поток для отправки обновлений отслеживания в источники браузера OBS. +- [i18next](https://github.com/i18next/) - с бэкэнд-коннектором для обслуживания + объектов локализации из слоя Go. +- [xstate](https://github.com/statelyai/xstate) — конечные автоматы для процесса + аутентификации и отслеживания. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx new file mode 100644 index 00000000000..c1817b70fff --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx @@ -0,0 +1,10 @@ +# EmailIt + +```mdx-code-block +

+ +
+

+``` + +[EmailIt](https://github.com/raguay/EmailIt/) is a Wails 2 program that is a markdown based email sender only with nine notepads, scripts to manipulate the text, and templates. It also has a scripts terminal to run scripts in EmailIt on files in your system. The scripts and templates can be used from the commandline itself or with the Alfred, Keyboard Maestro, Dropzone, or PopClip extensions. It also supports scripts and themes downloaded form GitHub. Documentation is not complete, but the programs works. It’s built using Wails2 and Svelte, and the download is a universal macOS application. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx new file mode 100644 index 00000000000..a03cc9bedc6 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx @@ -0,0 +1,12 @@ +# EncryptEasy + +```mdx-code-block +

+ +
+

+``` + +**[EncryptEasy](https://www.encrypteasy.app) - это простой и простой в использовании PGP инструмент шифрования, управления вашими ключами и ключами ваших контактов. Шифрование не должно быть сложным процессом для пользователя. Разработано на Wails.** + +Шифрование сообщений с помощью PGP является стандартом отрасли. У каждого есть приватный и публичный ключ. Ваш приватный ключ должен оставаться в секрете, для того, чтобы только вы могли читать сообщения. Ваш публичный ключ передается всем, кто хочет отправлять вам секретные и зашифрованные сообщения. Управление ключами, шифрованием сообщений и расшифровкой сообщений должно бесперебойно работать. EncryptEasy - это то, что позволяет сделать это с лёгкостью. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx new file mode 100644 index 00000000000..0fc168d6300 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx @@ -0,0 +1,13 @@ +# ESP Studio + +```mdx-code-block +

+ +
+

+``` + +[ESP Studio](https://github.com/torabian/esp-studio) - Кроссплатформенное, настольное, облачное и встроенное программное обеспечение +для управления устройствами ESP/Arduino и построения сложных рабочих процессов и систем управления IOT. \ No newline at end of file diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx new file mode 100644 index 00000000000..22b6d90816e --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx @@ -0,0 +1,16 @@ +# FileHound утилита для экспорта данных + +```mdx-code-block +

+ +
+

+``` + +[FileHound утилита для экспорта данных](https://www.filehound.co.uk/) FileHound это облачная платформа управления документами для безопасного сохранения файлов, автоматизации бизнес-процессов и SmartCapture возможностей. + +Утилита экспорта данных из FileHound позволяет администраторам запустить безопасное извлечение документов и данных для альтернативного варианта создания бэкапов и восстановления данных. Это приложение загруит все документы и/или метаданные, сохраненные в FileHound основываясь на выбранных фильтрах. Метадата будет извлечена в форматах XML и JSON. + +Бэкенд: Go 1.15 Wails 1.11.0 go-sqlite3 1.14.6 go-linq 3.2 + +Frontend with: Vue 2.6.11 Vuex 3.4.0 TypeScript Tailwind 1.9.6 diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx new file mode 100644 index 00000000000..87e5837d32f --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx @@ -0,0 +1,10 @@ +# hiposter + +```mdx-code-block +

+ +
+

+``` + +[hiposter](https://github.com/obity/hiposter) is a simple and efficient http API testing client tool. Based on Wails, Go and sveltejs. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx new file mode 100644 index 00000000000..b79e123cab4 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx @@ -0,0 +1,14 @@ +# Minecraft Updater + +```mdx-code-block +

+ +
+

+``` + +[Minecraft Updater](https://github.com/Gurkengewuerz/MinecraftModUpdater) — утилита для обновления и синхронизации Minecraft модов для вашей пользовательской базы. Она построена с помощью Wails2 и React с [antd](https://ant.design/) в качестве фронтенд фреймворка. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx new file mode 100644 index 00000000000..ed470b8bd55 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx @@ -0,0 +1,14 @@ +# Modal File Manager + +```mdx-code-block +

+ +
+

+``` + +[Modal File Manager](https://github.com/raguay/ModalFileManager) — это двухпанельный файловый менеджер с использованием веб-технологий. Мой оригинальный дизайн был основан на NW.js, и его можно найти [здесь](https://github.com/raguay/ModalFileManager-NWjs). В этой версии используется тот же код интерфейса Svelte (но с момента выхода из NW.), но бэкенд - это реализация [Wails 2](https://wails.io/). By using this implementation, I no longer use command line `rm`, `cp`, etc. commands, but a git install has to be on the system to download themes and extensions. Он полностью закодирован с помощью Go и работает гораздо быстрее, чем предыдущие версии. + +Этот файловый менеджер построен вокруг того же принципа, что и Vim: управление состоянием клавиатурных действий. Количество состояний не фиксировано, но очень программируется. Поэтому может быть создано и использовано бесконечное количество конфигураций клавиатуры. Это главное отличие от других файловых менеджеров. There are themes and extensions available to download from GitHub. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx new file mode 100644 index 00000000000..2795fc6241c --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx @@ -0,0 +1,10 @@ +# Molley Wallet + +```mdx-code-block +

+ +
+

+``` + +[Molly Wallet](https://github.com/grvlle/constellation_wallet/) официальный кошелек $DAG сети Constellation. Это позволит пользователям взаимодействовать с Hypergraph Network различными способами, не ограничиваясь $DAG транзакциями. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx new file mode 100644 index 00000000000..b9dbea1f888 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx @@ -0,0 +1,14 @@ +# October + +```mdx-code-block +

+ +
+

+``` + +[October](https://october.utf9k.net) - это небольшая программа Wails, которая позволяет извлечь выделения из [Kobo eReaders](https://en.wikipedia.org/wiki/Kobo_eReader) и затем переслать их в [Readwise](https://readwise.io). + +Он обладает относительно небольшим охватом со всеми версиями платформы, весом менее 10 МБ, и это без включения [UPX сжатия](https://upx.github.io/)! + +В отличие от этого, предыдущие попытки автора с Electron быстро вылились в несколько сот мегабайт. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx new file mode 100644 index 00000000000..24a41cbd6cd --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx @@ -0,0 +1,10 @@ +# Optimus + +```mdx-code-block +

+ +
+

+``` + +[Optimus](https://github.com/splode/optimus) - приложение для оптимизации изображений. Он поддерживает конвертацию и сжатие изображений между форматами WebP, JPEG и PNG. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx new file mode 100644 index 00000000000..1a9fa1eb7d5 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx @@ -0,0 +1,10 @@ +# Portfall + +```mdx-code-block +

+ +
+

+``` + +[Portfall](https://github.com/rekon-oss/portfall) - Портпад k8s портал для перенаправления портов для легкого доступа ко всем интерфейсам кластера diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx new file mode 100644 index 00000000000..5461ccf1af5 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx @@ -0,0 +1,12 @@ +# Restic Browser + +```mdx-code-block +

+ +
+

+``` + +[Restic-Browser](https://github.com/emuell/restic-browser) - Простой кросс-платформенный интерфейс для [restic](https://github.com/restic/restic) для просмотра и восстановления оставшихся репозиториев. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx new file mode 100644 index 00000000000..1b234072e13 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx @@ -0,0 +1,21 @@ +# RiftShare + +```mdx-code-block +

+ +
+

+``` + +Простой, безопасный и бесплатный обмен файлами для всех. Узнайте больше на [Riftshare.app](https://riftshare.app) + +## Возможности + +- Легкий обмен файлами между компьютерами как в локальной сети, так и через Интернет +- Поддерживает безопасную отправку файлов или директорий через [magic wormhole протокол](https://magic-wormhole.readthedocs.io/en/latest/) +- Совместимо со всеми приложениями, использующими magic wormhole (magic-wormhole или wormhole-william CLI, wormhole-gui и т. д.) +- Автоматическое сжатие нескольких выбранных файлов для одновременной отправки +- Полная анимация, индикатор прогресса и поддержка отмены для отправки и получения +- Нативное окно выбора файла +- Открытие файлов в один клик после получения +- Автоматическое обновление - не беспокойтесь о получении последней версии! diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx new file mode 100644 index 00000000000..a512448fe40 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx @@ -0,0 +1,10 @@ +# ScriptBar + +```mdx-code-block +

+ +
+

+``` + +[ScriptBar](https://GitHub.com/raguay/ScriptBarApp) is a program to show the output of scripts or [Node-Red](https://nodered.org) server. It runs scripts defined in EmailIt program and shows the output. Scripts from xBar or TextBar can be used, but currently on the TextBar scripts work well. Он также отображает вывод скриптов в вашей системе. ScriptBar не помещает их в меню, но все они в удобном окне для удобного просмотра. Вы можете открыть несколько вкладок, чтобы показать множество различных вещей. Вы также можете держать ссылки на наиболее посещаемые вами веб-сайты. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx new file mode 100644 index 00000000000..8f77bfb8a14 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx @@ -0,0 +1,10 @@ +# Surge + +```mdx-code-block +

+ +
+

+``` + +[Surge](https://getsurge.io/) это p2p приложение для обмена файлов, разработанное для использования блокчейн технологий для 100% анонимной передачи файлов. Surge зашифрован сквозным шифрованием, децентрализован и с открытым исходным кодом. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx new file mode 100644 index 00000000000..e3124bab727 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx @@ -0,0 +1,11 @@ +# Tiny RDM + +```mdx-code-block +

+ + +
+

+``` + +The [Tiny RDM](https://redis.tinycraft.cc/) application is an open-source, modern lightweight Redis GUI. It has a beautful UI, intuitive Redis database management, and compatible with Windows, Mac, and Linux. It provides visual key-value data operations, supports various data decoding and viewing options, built-in console for executing commands, slow log queries and more. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx new file mode 100644 index 00000000000..1d112481d06 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx @@ -0,0 +1,10 @@ +# Wally + +```mdx-code-block +

+ +
+

+``` + +[Wally](https://ergodox-ez.com/pages/wally) это официальное приложение для прошивки [Ergodox](https://ergodox-ez.com/) клавиатур. Это великолепный и фантастический пример того, чего вы можете достичь с помощью Wails: возможности сочетать мощь Go и богатые графические инструменты мира веб-разработки. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx new file mode 100644 index 00000000000..950dc3f3db1 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx @@ -0,0 +1,19 @@ +# Minecraft launcher for WarMine + +```mdx-code-block +

+ + +
+

+``` + +[Minecraft launcher for WarMine](https://warmine.ru/) is a Wails application, that allows you to easily join modded game servers and manage your game accounts. + +The Launcher downloads the game files, checks their integrity and launches the game with a wide range of customization options for the launch arguments from the backend. + +Frontend is written in Svelte, whole launcher fits in 9MB and supports Windows 7-11. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx new file mode 100644 index 00000000000..f526142ec28 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx @@ -0,0 +1,10 @@ +# Wombat + +```mdx-code-block +

+ +
+

+``` + +[Wombat](https://github.com/rogchap/wombat) - это кроссплатформенный клиент gRPC. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx new file mode 100644 index 00000000000..15be62e01e2 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx @@ -0,0 +1,10 @@ +# Ytd + +```mdx-code-block +

+ +
+

+``` + +[Ytd](https://github.com/marcio199226/ytd/tree/v2-wails) это приложение для скачивания треков с youtube, создания оффлайн плейлистов и обмена ими с друзьями, ваши друзья смогут воспроизвести ваши плейлисты или загрузить их для оффлайн прослушивания, имеет встроенный плеер. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx new file mode 100644 index 00000000000..0b86bb8d9bd --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx @@ -0,0 +1,69 @@ +--- +sidebar_position: 1 +--- + +# Шаблоны + +Эта страница служит списком шаблонов, поддерживаемых сообществом. Пожалуйста, отправьте PR (нажмите `Изменить эту страницу` внизу) чтобы включить ваши шаблоны. Чтобы создать свой собственный шаблон, см. [руководство по шаблонам](../guides/templates.mdx). + +Чтобы использовать эти шаблоны, запустите `wails init -n "Название вашего проекта" -t [ссылка ниже[@version]]` + +Если нет суффикса версии, по умолчанию используется основной шаблон кода ветки. При наличии суффикса версии используется кодовый шаблон, соответствующий тегу этой версии. + +Пример: `wails init -n "Project Name" -t https://github.com/misitebao/wails-template-vue` + +::warning Внимание + +**Проект Wails не поддерживает и не несет ответственности за сторонние шаблоны!** + +Если вы не уверены в шаблоне, проверьте `package.json` и `wails.json` на какие скрипты запускаются и какие пакеты установлены. + +::: + +## Vue + +- [wails-template-vue](https://github.com/misitebao/wails-template-vue) - шаблон, основанный на Vue ecology (ИнтегрированTypeScript, Темная тема, интернационализация, маршрутизация для одной страницы, TailwindCSS) +- [wails-vite-vue-ts](https://github.com/codydbentley/wails-vite-vue-ts) - Vue 3 TypeScript с Vite (и инструкции для добавления функций) +- [wails-vite-vue-the-works](https://github.com/codydbentley/wails-vite-vue-the-works) - Vue 3 TypeScript с Vite, Vuex, Vue Router, Sass, и ESLint + Prettier +- [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - A template using JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier) +- [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - A template using TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier, Composition API with <script setup>) +- [wails-template-naive](https://github.com/tk103331/wails-template-naive) - Wails template based on Naive UI (A Vue 3 Component Library) + +## Angular + +- [wails-template-angular](https://github.com/mateothegreat/wails-template-angular) - Angular 15+ action packed & ready to roll to production. +- [wails-угловый-template](https://github.com/TAINCER/wails-angular-template) - Angular с TypeScript, Sass, Hot-Reload, Code-Splitting и i18n + +## React + +- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - Шаблон с использованием reactjs +- [wails-react-template](https://github.com/flin7/wails-react-template) - минимальный шаблон для React, который поддерживает живую разработку +- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - шаблон с использованием Next.js и TypeScript +- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - шаблон для React + TypeScript + Vite + TailwindCSS +- [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - A template with Vite, React, TypeScript, TailwindCSS, and shadcn/ui + +## Svelte + +- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - шаблон с использованием Svelte +- [wails-vite-template](https://github.com/BillBuilt/wails-vite-svelte-template) - шаблон с использованием Svelte и Vite +- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - шаблон с использованием Svelte и Vite с TailwindCSS v3 +- [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - An updated template using Svelte v4.2.0 and Vite with TailwindCSS v3.3.3 +- [wails-sveltekit-template](https://github.com/h8gi/wails-sveltekit-template) - шаблон с использованием SvelteKit + +## Solid + +- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-ts) - A template using Solid + Ts + Vite +- [wails-template-vite-solid-js](https://github.com/xijaja/wails-template-solid-js) - A template using Solid + Js + Vite + +## Elm + +- [wails-elm-шаблон](https://github.com/benjamin-thomas/wails-elm-template) - Разработайте ваше GUI приложение с функциональным программированием и **snappy** настройками горячей перезагрузки :tada: :rocket: +- [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - Объединение возможностей :muscle: Elm + Tailwind CSS + Wails! Поддерживается горячая перезагрузка. + +## HTMX + +- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - Use a unique combination of pure htmx for interactivity plus templ for creating components and forms + +## Чистый JavaScript (Vanilla) + +- [wails-pure-js-шаблон](https://github.com/KiddoV/wails-pure-js-template) - шаблон, содержащий только базовый JavaScript, HTML и CSS diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx new file mode 100644 index 00000000000..11122314cdc --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx @@ -0,0 +1,22 @@ +--- +sidebar_position: 6 +--- + +# Компиляция проекта + +Из каталога проекта запустите `wails build`. Это позволит скомпилировать ваш проект и сохранить готовый к выпуску бинарный файл в директории `build/bin`. + +Если вы запустите исполняемый файл, вы увидите приложение по умолчанию: + +```mdx-code-block +
+ +
+
+``` + +Для получения более подробной информации о параметрах компиляции обратитесь к [CLI Reference](../reference/cli.mdx#build). diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx new file mode 100644 index 00000000000..e7c6351e782 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx @@ -0,0 +1,16 @@ +--- +sidebar_position: 5 +--- + +# Разработка вашего приложения + +Вы можете запустить ваше приложение в режиме разработки, выполнив `wails dev` в вашем каталоге проекта. Это сделает следующие вещи: + +- Соберет ваше приложение и запустит +- Bind your Go code to the frontend so it can be called from JavaScript +- С помощью [Vite](https://vitejs.dev/), будет наблюдать за изменениями в ваших Go файлах и пересобирать/перезапускать при изменении +- Устанавливает [веб-сервер](http://localhost:34115), который будет обслуживать ваше приложение через браузер. Это позволит вам использовать ваши любимые расширения браузера. Вы даже можете вызвать ваш Go-код из консоли + +Для начала запустите `wails dev` в каталоге проекта. Более подробную информацию об этом можно найти [здесь](../reference/cli.mdx#dev). + +Скоро: Инструкция diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx new file mode 100644 index 00000000000..52b58fa7757 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 2 +--- + +# Создание проекта + +## Генерация проекта + +Теперь, когда CLI установлен, вы можете создать новый проект, используя команду `wails init`. + +Выберите Ваш любимый фреймворк: + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + Generate a Svelte project using JavaScript with:

+ + wails init -n myproject -t svelte + +If you would rather use TypeScript:
+ + wails init -n myproject -t svelte-ts + +
+ + Generate a React project using JavaScript with:

+ + wails init -n myproject -t react + +If you would rather use TypeScript:
+ + wails init -n myproject -t react-ts + +
+ + Generate a Vue project using JavaScript with:

+ + wails init -n myproject -t vue + +If you would rather use TypeScript:
+ + wails init -n myproject -t vue-ts + +
+ + Generate a Preact project using JavaScript with:

+ + wails init -n myproject -t preact + +If you would rather use TypeScript:
+ + wails init -n myproject -t preact-ts + +
+ + Generate a Lit project using JavaScript with:

+ + wails init -n myproject -t lit + +If you would rather use TypeScript:
+ + wails init -n myproject -t lit-ts + +
+ + Generate a Vanilla project using JavaScript with:

+ + wails init -n myproject -t vanilla + +If you would rather use TypeScript:
+ + wails init -n myproject -t vanilla-ts + +
+
+``` + +
+ +Доступны также [шаблоны сообщества](../community/templates.mdx), которые предлагают различные возможности и фреймворки. + +Чтобы увидеть другие доступные опции, вы можете запустить `wails init -help`. Более подробную информацию можно найти в [CLI Reference](../reference/cli.mdx#init). + +## Структура проекта + +Проекты Wails имеют следующую структуру: + +``` +. +├── build/ +│ ├── appicon.png +│ ├── darwin/ +│ └── windows/ +├── frontend/ +├── go.mod +├── go.sum +├── main.go +└── wails.json +``` + +### Краткое описание структуры проекта + +- `/main.go` - основное приложение +- `/frontend/` - фронтенд файлы проекта +- `/build/` - директория сборки проекта +- `/build/appicon.png` - значок приложения +- `/build/darwin/` - файлы проекта для Mac +- `/build/windows/` - файлы проектов, специфичных для Windows +- `/wails.json` - Конфигурация проекта +- `/go.mod` - Go module файл +- `/go.sum` - Go module проверочная сумма + +Каталог `frontend` ничего не имеет специфического для Wails и может быть любым пользовательским проектом по вашему выбору. + +Каталог `build` используется в процессе сборки. Эти файлы можно обновить, чтобы настроить ваши сборки. Если удалить файлы из директории, они будут заново сгенерированы с версией по-умолчанию. + +Название модуля по умолчанию в `go.mod` - это "changeme". Вы должны изменить это на нечто более подходящее. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx new file mode 100644 index 00000000000..b69ab2d4c76 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx @@ -0,0 +1,90 @@ +--- +sidebar_position: 1 +--- + +# Инструкция по установке + +## Поддерживаемые платформы + +- Windows 10/11 AMD64/ARM64 +- MacOS 10.13+ AMD64 +- MacOS 11.0+ ARM64 +- Linux AMD64/ARM64 + +## Зависимости + +Wails имеет ряд общих зависимостей, которые необходимы перед установкой: + +- Go 1.18+ +- NPM (Node 15+) + +### Go + +Скачайте Go с [Go Downloads Page](https://go.dev/dl/). + +Убедитесь, что вы следуете официальным [Инструкциям по установке](https://go.dev/doc/install). Вам также нужно убедиться, что ваша переменная окружения `PATH` также включает путь к вашему каталогу `~/go/bin`. Перезапустите терминал и выполните следующие шаги: + +- Проверьте то, что Go установлен правильно: `go version` +- Проверьте "~/go/bin" в переменной PATH: `echo $PATH | grep go/bin` + +### NPM + +Загрузите NPM отсюда: [Node Downloads Page](https://nodejs.org/en/download/). Лучше использовать последнюю версию, так как это то, что мы её обычно тестируем. + +Запустите `npm --version` для проверки. + +## Зависимости платформы + +Вам также нужно установить специфичные для платформы зависимости: + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + Wails требует установки инструментов xcode command line tools. Их можно установить, + запустив xcode-select --install. + + + Wails требует установки WebView2. В некоторых установках Windows это уже установлено. Вы можете проверить используя команду wails doctor. + + + Linux requires the standard gcc build tools plus libgtk3 and libwebkit. Вместо того чтобы перечислять огромное количество команд для разных дистрибутивов, Wails может попробовать определить команды установки, специфичные для вашего дистрибутива. Запустите wails doctor после установки, чтобы узнать, как установить зависимости. Если ваш дистрибутив или менеджер пакетов не поддерживается, пожалуйста, обратитесь к руководству {" "} Добавление дистрибутива Linux. + + +``` + +## Необязательные зависимости + +- [UPX](https://upx.github.io/) для сжатия приложений. +- [NSIS](https://wails.io/docs/guides/windows-installer/) for generating Windows installers. + +## Установка Wails + +Выполните `go install github.com/wailsapp/wails/v2/cmd/wails@latest` для установки Wails CLI. + +Примечание: Если вы получите ошибку, похожую на эту: + +```shell +....\Go\pkg\mod\github.com\wailsapp\wails\v2@v2.1.0\pkg\templates\templates.go:28:12: pattern all:ides/*: no matching files found +``` +пожалуйста, убедитесь, что у вас установлен Go 1.18+: +```shell +go version +``` + +## Проверка системы + +Запуск `wails doctor` проверит установлены ли у вас правильные зависимости. Если нет, то он покажет что не хватает, и покажет как исправить какие-либо проблемы. + +## Отсутствует команда `wails`? + +Если ваша система пишет, что команда `wails` отсутствует, удостоверьтесь, что вы корректно следовали инструкции по установке Go. Обычно это значит, что папка `go/bin`, находящаяся в домашней папке пользователя не добавлена в переменную окружения `PATH`. Обычно после изменения переменных окружения нужно переоткрыть командную строку, чтобы изменения применились в ней. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx new file mode 100644 index 00000000000..4d56b65bba1 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx @@ -0,0 +1,14 @@ +# Angular + +Хотя у Wails нет шаблона с Angular, тем не менее Angular использовать возможно. + +## Режим разработчика + +Чтобы получить режим dev работы с Angular, вам нужно добавить следующие значения к `wails.json`: + +```json + "frontend:build": "npx ng build", + "frontend:install": "npm install", + "frontend:dev:watcher": "npx ng serve", + "frontend:dev:serverUrl": "http://localhost:4200", +``` \ No newline at end of file diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx new file mode 100644 index 00000000000..f9e723fee41 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx @@ -0,0 +1,215 @@ +# Разработка приложения + +Нет жестких и быстрых правил для разработки приложений с помощью Wails, но есть некоторые основные принципы. + +## Application Setup + +The pattern used by the default templates are that `main.go` is used for configuring and running the application, whilst `app.go` is used for defining the application logic. + +The `app.go` file will define a struct that has 2 methods which act as hooks into the main application: + +```go title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} +``` + +- The startup method is called as soon as Wails allocates the resources it needs and is a good place for creating resources, setting up event listeners and anything else the application needs at startup. It is given a `context.Context` which is usually saved in a struct field. This context is needed for calling the [runtime](../reference/runtime/intro.mdx). If this method returns an error, the application will terminate. In dev mode, the error will be output to the console. + +- The shutdown method will be called by Wails right at the end of the shutdown process. This is a good place to deallocate memory and perform any shutdown tasks. + +The `main.go` file generally consists of a single call to `wails.Run()`, which accepts the application configuration. The pattern used by the templates is that before the call to `wails.Run()`, an instance of the struct we defined in `app.go` is created and saved in a variable called `app`. This configuration is where we add our callbacks: + +```go {3,9,10} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +More information on application lifecycle hooks can be found [here](../howdoesitwork.mdx#application-lifecycle-callbacks). + +## Binding Methods + +It is likely that you will want to call Go methods from the frontend. This is normally done by adding public methods to the already defined struct in `app.go`: + +```go {16-18} title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +In the main application configuration, the `Bind` key is where we can tell Wails what we want to bind: + +```go {11-13} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +This will bind all public methods in our `App` struct (it will never bind the startup and shutdown methods). + +### Dealing with context when binding multiple structs + +If you want to bind methods for multiple structs but want each struct to keep a reference to the context so that you can use the runtime functions, a good pattern is to pass the context from the `OnStartup` method to your struct instances : + +```go +func main() { + + app := NewApp() + otherStruct := NewOtherStruct() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: func(ctx context.Context){ + app.SetContext(ctx) + otherStruct.SetContext(ctx) + }, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + otherStruct + }, + }) + if err != nil { + log.Fatal(err) + } +} +``` + +More information on Binding can be found [here](../howdoesitwork.mdx#method-binding). + +## Application Menu + +Wails supports adding a menu to your application. This is done by passing a [Menu](../reference/menus.mdx#menu) struct to application config. It's common to use a method that returns a Menu, and even more common for that to be a method on the `App` struct used for the lifecycle hooks. + +```go {11} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Menu: app.menu(), + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +## Assets + +The great thing about the way Wails v2 handles assets is that it doesn't! The only thing you need to give Wails is an `embed.FS`. How you get to that is entirely up to you. You can use vanilla html/css/js files like the vanilla template. You could have some complicated build system, it doesn't matter. + +When `wails build` is run, it will check the `wails.json` project file at the project root. There are 2 keys in the project file that are read: + +- "frontend:install" +- "frontend:build" + +The first, if given, will be executed in the `frontend` directory to install the node modules. The second, if given, will be executed in the `frontend` directory to build the frontend project. + +If these 2 keys aren't given, then Wails does absolutely nothing with the frontend. It is only expecting that `embed.FS`. + +### AssetsHandler + +A Wails v2 app can optionally define a `http.Handler` in the `options.App`, which allows hooking into the AssetServer to create files on the fly or process POST/PUT requests. GET requests are always first handled by the `assets` FS. If the FS doesn't find the requested file the request will be forwarded to the `http.Handler` for serving. Any requests other than GET will be directly processed by the `AssetsHandler` if specified. It's also possible to only use the `AssetsHandler` by specifiy `nil` as the `Assets` option. + +## Built in Dev Server + +Running `wails dev` will start the built in dev server which will start a file watcher in your project directory. By default, if any file changes, wails checks if it was an application file (default: `.go`, configurable with `-e` flag). If it was, then it will rebuild your application and relaunch it. If the changed file was in the assets, it will issue a reload after a short amount of time. + +The dev server uses a technique called "debouncing" which means it doesn't reload straight away, as there may be multiple files changed in a short amount of time. When a trigger occurs, it waits for a set amount of time before issuing a reload. If another trigger happens, it resets to the wait time again. By default this value is `100ms`. If this value doesn't work for your project, it can be configured using the `-debounce` flag. If used, this value will be saved to your project config and become the default. + +## External Dev Server + +Some frameworks come with their own live-reloading server, however they will not be able to take advantage of the Wails Go bindings. In this scenario, it is best to run a watcher script that rebuilds the project into the build directory, which Wails will be watching. For an example, see the default svelte template that uses [rollup](https://rollupjs.org/guide/en/). + +### Create React App + +The process for a Create-React-App project is slightly more complicated. In order to support live frontend reloading the following configuration needs to be added to your `wails.json`: + +```json + "frontend:dev:watcher": "yarn start", + "frontend:dev:serverUrl": "http://localhost:3000", +``` + +The `frontend:dev:watcher` command will start the Create-React-App development server (hosted on port `3000` typically). The `frontend:dev:serverUrl` command then instructs Wails to serve assets from the development server when loading the frontend rather than from the build folder. In addition to the above, the `index.html` needs to be updated with the following: + +```html + + + + + +``` + +This is required as the watcher command that rebuilds the frontend prevents Wails from injecting the required scripts. This circumvents that issue by ensuring the scripts are always injected. With this configuration, `wails dev` can be run which will appropriately build the frontend and backend with hot-reloading enabled. Additionally, when accessing the application from a browser the React developer tools can now be used on a non-minified version of the application for straightforward debugging. Finally, for faster builds, `wails dev -s` can be run to skip the default building of the frontend by Wails as this is an unnecessary step. + +## Go Module + +The default Wails templates generate a `go.mod` file that contains the module name "changeme". You should change this to something more appropriate after project generation. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx new file mode 100644 index 00000000000..fd81a974d04 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx @@ -0,0 +1,66 @@ +# Crossplatform build with Github Actions + +To build a Wails project for all the available platforms, you need to create an application build for each operating system. One effective method to achieve this is by utilizing GitHub Actions. + +An action that facilitates building a Wails app is available at: +https://github.com/dAppServer/wails-build-action + +In case the existing action doesn't fulfill your requirements, you can select only the necessary steps from the source: +https://github.com/dAppServer/wails-build-action/blob/main/action.yml + +Below is a comprehensive example that demonstrates building an app upon the creation of a new Git tag and subsequently uploading it to the Actions artifacts: + +```yaml +name: Wails build + +on: + push: + tags: + # Match any new tag + - '*' + +env: + # Necessary for most environments as build failure can occur due to OOM issues + NODE_OPTIONS: "--max-old-space-size=4096" + +jobs: + build: + strategy: + # Failure in one platform build won't impact the others + fail-fast: false + matrix: + build: + - name: 'App' + platform: 'linux/amd64' + os: 'ubuntu-latest' + - name: 'App' + platform: 'windows/amd64' + os: 'windows-latest' + - name: 'App' + platform: 'darwin/universal' + os: 'macos-latest' + + runs-on: ${{ matrix.build.os }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Build wails + uses: dAppServer/wails-build-action@v2.2 + id: build + with: + build-name: ${{ matrix.build.name }} + build-platform: ${{ matrix.build.platform }} + package: false + go-version: '1.20' +``` + +This example offers opportunities for various enhancements, including: + +- Caching dependencies +- Code signing +- Uploading to platforms like S3, Supbase, etc. +- Injecting secrets as environment variables +- Utilizing environment variables as build variables (such as version variable extracted from the current Git tag) diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx new file mode 100644 index 00000000000..e86b651845d --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx @@ -0,0 +1,204 @@ +# Custom Protocol Scheme association + +Custom Protocols feature allows you to associate specific custom protocol with your app so that when users open links with this protocol, +your app is launched to handle them. This can be particularly useful to connect your desktop app with your web app. +In this guide, we'll walk through the steps to implement custom protocols in Wails app. + +## Set Up Custom Protocol Schemes Association: + +To set up custom protocol, you need to modify your application's wails.json file. +In "info" section add a "protocols" section specifying the protocols your app should be associated with. + +For example: + +```json +{ + "info": { + "protocols": [ + { + "scheme": "myapp", + "description": "My App Protocol", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------ | +| scheme | Custom Protocol scheme. e.g. myapp | +| description | Windows-only. The description. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open custom protocol with your app, the system will launch your app and call the `OnUrlOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnUrlOpen: func(url string) { println(url) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows Custom Protocol Schemes is supported only with NSIS installer. During installation, the installer will create a +registry entry for your schemes. When you open url with your app, new instance of app is launched and url is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there (note that `%u` is important in Exec). Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=x-scheme-handler/myapp; +``` + +2. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +``` + +3. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with custom protocol scheme. When you open url with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx new file mode 100644 index 00000000000..975916524b4 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx @@ -0,0 +1,136 @@ +# Динамические ресурсы + +Если вы хотите загрузить или генерировать ресурсы для вашего фронтенда динамически, вы можете это сделать, используя опцию [AssetsHandler](../reference/options#assetshandler). AssetsHandler это общий `http.Handler`, который будет вызываться для любого запроса, не являющегося GET, на сервере ресурсов и для запросов GET, которые не могут быть обработаны из бандла ресурсов, поскольку файл не найден. + +Установив пользовательские AssetsHandler, вы можете предоставлять свои собственные ресурсы с помощью пользовательского ресурсного сервера. + +## Пример + +В нашем примере мы создадим простой обработчик ресурсов, который загрузит файлы с диска: + +```go title=main.go {17-36,49} +package main + +import ( + "embed" + "fmt" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "net/http" + "os" + "strings" +) + +//go:embed all:frontend/dist +var assets embed.FS + +type FileLoader struct { + http.Handler +} + +func NewFileLoader() *FileLoader { + return &FileLoader{} +} + +func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) { + var err error + requestedFilename := strings.TrimPrefix(req.URL.Path, "/") + println("Requesting file:", requestedFilename) + fileData, err := os.ReadFile(requestedFilename) + if err != nil { + res.WriteHeader(http.StatusBadRequest) + res.Write([]byte(fmt.Sprintf("Could not load file %s", requestedFilename))) + } + + res.Write(fileData) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "helloworld", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: NewFileLoader(), + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 255}, + OnStartup: app.startup, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +Когда мы запустим приложение в dev режиме, с помощью команды `wails dev`, мы увидим следующий вывод: + +``` +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' failed, using AssetHandler +Requesting file: favicon.ico +``` + +Как видите, обработчик ресурсов вызывается, когда стандартный сервер ресурсов не может предоставить файл `favicon.ico`. + +Если вы щелкните правой кнопкой мыши по окну приложения и выберите "Исследовать элемент" для вызова devtools, вы сможете протестировать эту функцию, введя в консоль следующую строку: + +``` +let response = await fetch('does-not-exist.txt'); +``` + +Это сгенерирует ошибку в devtools. Мы видим ошибку обработчика пользовательских ресурсов, которую мы ожидали увидеть: + +```mdx-code-block +

+ +

+``` + +Однако, если мы вызовем `go.mod`, мы увидим следующий вывод: + +```mdx-code-block +

+ +

+``` + +А так мы можем разместить изображение прямо на страницу. Если мы обновим шаблон по умолчанию и заменим изображение логотипа: + +```html + +``` + +на: + +```html + +``` + +Тогда мы увидим следующее: + +```mdx-code-block +

+ +

+``` + +:::warning + +Раскрытие структуры файловой системы таким образом сопряжено с рисками безопасности. Рекомендуется правильно управлять доступом к файловой системе. + +::: diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx new file mode 100644 index 00000000000..167955b12d7 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx @@ -0,0 +1,244 @@ +# File Association + +File association feature allows you to associate specific file types with your app so that when users open those files, +your app is launched to handle them. This can be particularly useful for text editors, image viewers, or any application +that works with specific file formats. In this guide, we'll walk through the steps to implement file association in Wails app. + +## Set Up File Association: + +To set up file association, you need to modify your application's wails.json file. +In "info" section add a "fileAssociations" section specifying the file types your app should be associated with. + +For example: + +```json +{ + "info": { + "fileAssociations": [ + { + "ext": "wails", + "name": "Wails", + "description": "Wails Application File", + "iconName": "wailsFileIcon", + "role": "Editor" + }, + { + "ext": "jpg", + "name": "JPEG", + "description": "Image File", + "iconName": "jpegFileIcon", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | +| ext | The extension (minus the leading period). e.g. png | +| name | The name. e.g. PNG File | +| iconName | The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows | +| description | Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open file (or files) with your app, the system will launch your app and call the `OnFileOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnFileOpen: func(filePaths []string) { println(filestring) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows file association is supported only with NSIS installer. During installation, the installer will create a +registry entry for your file associations. When you open file with your app, new instance of app is launched and file path is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there. Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=application/x-wails;application/x-test +``` + +2. Create mime types file. Example: + +```xml + + + + Wails Application File + + + +``` + +3. Create icons for your file types. SVG icons are recommended. +4. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload mime types to register file associations +update-mime-database /usr/share/mime +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +# update icons +update-icon-caches /usr/share/icons/* +``` + +5. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ./application-wails-mime.xml + dst: /usr/share/mime/packages/application-x-wails.xml +- src: ./application-test-mime.xml + dst: /usr/share/mime/packages/application-x-test.xml +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with specified file types. When you open file with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx new file mode 100644 index 00000000000..1c7a661e794 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx @@ -0,0 +1,87 @@ +# Безрамочные приложения + +Wails поддерживает приложения, не имеющие рамок. Этого можно добиться, используя поле [frameless](../reference/options.mdx#frameless) в [опциях приложения](../reference/options.mdx#application-options). + +Wails предоставляет легкое решение для перемещения окна: любой HTML элемент имеющий стиль `--wails-draggable:drag` будет работать как "ручка для перетаскивания". Это свойство применяется для всех дочерних элементов. Если вам необходимо указать, что вложенный элемент не должен перестаскивать окно, то используйте атрибут '--wails-draggable:no-drag' на этом элементе. + +```html + + + + + + + +
+ + +
+
+ + + + +``` + +Для некоторых проектов использование CSS переменной может оказаться невозможным из-за динамических стилей. В этом случае вы можете использовать параметры `CSSDragProperty` и `CSSDragValue` в опциях приожения для определения свойства и значения, которые будут использоваться для указания перетаскиваемых областей: + +```go title=main.go +package main + +import ( + "embed" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + // Создаем экземляр структуры приложения + app := NewApp() + + // Создаем приложение с опциями + err := wails.Run(&options.App{ + Title: "alwaysontop", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Frameless: true, + CSSDragProperty: "widows", + CSSDragValue: "1", + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +```html title=index.html + + + + + + alwaysontop + + +
+ + + +``` + +:::info Fullscreen + +Если вы разрешите приложению перейти в полноэкранный режим, функция перетаскивания будет отключена. + +::: diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx new file mode 100644 index 00000000000..ac087ee4514 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx @@ -0,0 +1,72 @@ +# Frontend + +## Script Injection + +When Wails serves your `index.html`, by default, it will inject 2 script entries into the `` tag to load `/wails/ipc.js` and `/wails/runtime.js`. These files install the bindings and runtime respectively. + +The code below shows where these are injected by default: + +```html + + + injection example + + + + + + + +
Please enter your name below 👇
+
+ + +
+ + + + +``` + +### Overriding Default Script Injection + +To provide more flexibility to developers, there is a meta tag that may be used to customise this behaviour: + +```html + +``` + +The options are as follows: + +| Value | Description | +| ------------------- | ------------------------------------------------ | +| noautoinjectruntime | Disable the autoinjection of `/wails/runtime.js` | +| noautoinjectipc | Disable the autoinjection of `/wails/ipc.js` | +| noautoinject | Disable all autoinjection of scripts | + +Multiple options may be used provided they are comma seperated. + +This code is perfectly valid and operates the same as the autoinjection version: + +```html + + + injection example + + + + + + +
Please enter your name below 👇
+
+ + +
+ + + + + + +``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx new file mode 100644 index 00000000000..9319fbb2371 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx @@ -0,0 +1,127 @@ +# IDEs + +Wails aims to provide a great development experience. To that aim, we now support generating IDE specific configuration to provide smoother project setup. + +Currently, we support [Visual Studio Code](https://code.visualstudio.com/) but aim to support other IDEs such as Goland. + +## Visual Studio Code + +```mdx-code-block +

+ +

+``` + +When generating a project using the `-ide vscode` flags, IDE files will be created alongside the other project files. Эти файлы помещаются в директорию `.vscode` и предоставляют правильную конфигурацию для отладки вашего приложения. + +The 2 files generated are `tasks.json` and `launch.json`. Below are the files generated for the default vanilla project: + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/myproject.exe" + ] + } + ] +} +``` + +```json title="launch.json" +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Wails: Debug myproject", + "type": "go", + "request": "launch", + "mode": "exec", + "program": "${workspaceFolder}/build/bin/myproject.exe", + "preLaunchTask": "build", + "cwd": "${workspaceFolder}", + "env": {} + } + ] +} +``` + +### Configuring the install and build steps + +The `tasks.json` file is simple for the default project as there is no `npm install` or `npm run build` step needed. For projects that have a frontend build step, such as the svelte template, we would need to edit `tasks.json` to add the install and build steps: + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "npm install", + "type": "npm", + "script": "install", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "npm run build", + "type": "npm", + "script": "build", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/vscode.exe" + ], + "dependsOn": ["npm install", "npm run build"] + } + ] +} +``` + +:::info Future Enhancement + +In the future, we hope to generate a `tasks.json` that includes the install and build steps automatically. + +::: diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx new file mode 100644 index 00000000000..10750baaf09 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx @@ -0,0 +1,103 @@ +# Поддержка Linux + +## Обзор + +Wails предлагает поддержку Linux, но составить инструкции по установке для всех доступных дистрибутивов - это невыполнимая задача. Вместо этого Wails пытается определить, доступны ли пакеты для разработки через системный менеджер пакетов. В настоящее время мы поддерживаем следующие менеджеры пакетов: + +- apt +- dnf +- emerge +- eopkg +- nixpkgs +- pacman +- zypper + +## Добавление имен пакетов + +Может возникнуть ситуация, когда ваш дистрибутив использует один из поддерживаемых менеджеров пакетов, но имя пакета отличается от названия. Например, вы можете использовать производную от Ubuntu систему, но имя пакета для gtk может быть другим. Wails пытается найти правильный пакет, ища по списку имен пакетов. Список пакетов хранится в файле (packagemanager) в каталоге `v2/internal/system/packagemanager`. В нашем примере это `v2/internal/system/packagemanager/apt.go`. + +В этом файле список пакетов определяется методом `Packages()`: + +```go +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +Предположим, что в нашем Linux-дистрибутиве `libgtk-3` упакован под именем `lib-gtk3-dev`. Мы могли бы добавить поддержку для этого, добавив следующую строку: + +```go {5} +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + {Name: "lib-gtk3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +## Добавление новых менеджеров пакетов + +Чтобы добавить новый менеджер пакетов, выполните следующие действия: + +- Создайте новый файл в `v2/internal/system/packagemanager` под названием `.go`, где `` это имя менеджера пакетов. +- Определите структуру, которая соответствует интерфейсу менеджера пакетов, определенному в `pm.go`: + +```go +type PackageManager interface { + Name() string + Packages() packagemap + PackageInstalled(*Package) (bool, error) + PackageAvailable(*Package) (bool, error) + InstallCommand(*Package) string +} +``` + +- `Name()` должен возвращать имя менеджера пакетов +- `Packages()` должен возвращать `packagemap`, который предоставляет имена файлов для зависимостей +- `PackageInstalled()` должен возвращать `true`, если данный пакет установлен +- `PackageAvailable()` должен возвращать `true`, если данный пакет не установлен, но доступен для установки +- `InstallCommand()` должен возвращать точную команду для установки данного пакета + +Взгляните на другие коды менеджеров пакетов, чтобы получить представление о том, как это работает. + +::info Помните + +Если вы добавите поддержку для нового менеджера пакетов, не забудьте также обновить эту страницу! + +::: diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx new file mode 100644 index 00000000000..229c282bf55 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx @@ -0,0 +1,18 @@ +# Linux + +This page has miscellaneous guides related to developing Wails applications for Linux. + +## Video tag doesn't fire "ended" event + +When using a video tag, the "ended" event is not fired when the video is finished playing. This is a bug in WebkitGTK, however you can use the following workaround to fix it: + +```js +videoTag.addEventListener("timeupdate", (event) => { + if (event.target.duration - event.target.currentTime < 0.2) { + let ended = new Event("ended"); + event.target.dispatchEvent(ended); + } +}); +``` + +Source: [Lyimmi](https://github.com/Lyimmi) on the [discussions board](https://github.com/wailsapp/wails/issues/1729#issuecomment-1212291275) diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx new file mode 100644 index 00000000000..4ba1f34c37d --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx @@ -0,0 +1,55 @@ +# Local Development + +## Overview + +Wails is in constant development and new releases are regularly "tagged". This usually happens when all the newer code on `master` has been tested and confirmed working. If you need a bugfix or feature that has not yet made it to a release, it's possible to use the latest "bleeding edge" version using the following steps: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails/v2/cmd/wails` +- `go install` + +NOTE: The directory that you cloned the project into will now be called "clonedir". + +The Wails CLI will now be at the very latest version. + +### Updating your project + +To update projects to use the latest version of the Wails library, update the project's `go.mod` and ensure the following line is at the bottom of the file: + +`replace github.com/wailsapp/wails/v2 => ` + +Example: + +On Windows: `replace github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2` + +On 'nix: `replace github.com/wailsapp/wails/v2 => /home/me/projects/wails/v2` + +To revert to a stable version, run: + +`go install github.com/wailsapp/wails/v2/cmd/wails@latest` + +## Testing a Branch + +If you want to test a branch, follow the instructions above, but ensure you switch the branch you want to test before installing: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails` +- `git checkout -b branch-to-test --track origin/branch-to-test` +- `cd v2/cmd/wails` +- `go install` + +Make sure you [update your project](#updating-your-project) as described above. + +## Testing a PR + +If you want to test a PR, follow the instructions above, but ensure you fetch the PR and switch the branch before installing. Please replace `[IDofThePR]` with the ID of the PR shown on github.com: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails` +- `git fetch -u origin pull/[IDofThePR]/head:test/pr-[IDofThePR]` +- `git checkout test/pr-[IDofThePR]` +- `git reset --hard HEAD` +- `cd v2/cmd/wails` +- `go install` + +Make sure you [update your project](#updating-your-project) as described above. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx new file mode 100644 index 00000000000..961595711c7 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx @@ -0,0 +1,97 @@ +# Mac App Store Guide + +This page gives a brief overview of how to submit your Wails App to the Mac App Store. + +## Prerequisites + +- You will need to have an Apple Developer account. Please find more information on the [Apple Developer Program](https://developer.apple.com/support/compare-memberships/) site +- You will need to have your Certificates, Identifiers, and App created on the developer portal. More on this below +- Xcode command line tools will need to be installed on your local machine + +#### Create Certificates and Identifiers + +1. Go to your [Apple Developer Account](https://developer.apple.com/account/) +2. Under `Certificates, Identifiers & Profiles`, click `Identifiers` and Register a New App ID. Use the format (com.example.app) +3. Under the same page click `Certificates` and generate new Certificates for Mac App Store Distribution. Download them and import the certificates into Keychain on your local machine. + +#### Create App Submission + +1. Go to the [App Store Connect Site](https://appstoreconnect.apple.com/apps) +2. Register a new application and link the bundle ID that you created in the previous step +3. Populate your app with the correct screen shots, descriptions, etc. as required by Apple +4. Create a new version of your app + +#### Create Provisioning Profile +1. Go to the [Apple Developer Profiles](https://developer.apple.com/account/resources/profiles/list) page +2. Add a new provisioning profile for Mac App Store Distribution +3. Set the Profile Type as Mac and select the App ID for the application created above +4. Select the Mac App Distribution certificate +5. Name the Provisioning Profile embedded and download the created profile. + +## Mac App Store Process + +#### Enable Apple's App Sandbox + +Apps submitted to the Mac App Store must run under Apple's [App Sandbox](https://developer.apple.com/app-sandboxing/). You must create an `entitlements.plist` file for this to work. The recommendation is to create this file under this path `{PROJECT_DIR}/build/darwin/entitlements.plist`. + +**Example Entitlements File** + +This is an example entitlements file from the [RiftShare](https://github.com/achhabra2/riftshare) app. For reference please put in the entitlements your app requires. Refer to [this site](https://developer.apple.com/documentation/bundleresources/entitlements) for more information. You will need to replace the Team ID and Application Name with the ones you registered above. + +```xml title="entitlements.plist" + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + com.apple.application-identifier + TEAM_ID.APP_NAME + com.apple.developer.team-identifier + TEAM_ID + + +``` + +**Add the Embedded Provisioning Profile** The Provisioning Profile created above needs to be added to the root of the applicaton. It needs to be named embedded.provisionprofile. + +#### Build and Sign the App Package + +The following is an example script for building and signing your app for Mac App Store submission. It assumes you are running the script from your root project directory. + +Note the certificates for signing the app and signing the installer are different. Please make sure both are imported into Keychain. Find the strings in Keychain and insert them below. Populate your certificate names, and app name below. Running the following script will generate a signed `app.pkg` file in the root directory of your app. + +```bash title="macappstore-build.sh" +#!/bin/bash + +APP_CERTIFICATE="3rd Party Mac Developer Application: YOUR NAME (CODE)" +PKG_CERTIFICATE="3rd Party Mac Developer Installer: YOUR NAME (CODE)" +APP_NAME="YourApp" + +wails build -platform darwin/universal -clean + +cp ./embedded.provisionprofile "./build/bin/$APP_NAME.app/Contents" + +codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist ./build/bin/$APP_NAME.app + +productbuild --sign "$PKG_CERTIFICATE" --component ./build/bin/$APP_NAME.app /Applications ./$APP_NAME.pkg +``` + +#### Upload App Bundle + +You will need to upload the generated package file and associate it to your Application before you will be able to submit it for review. + +1. Download the [Transporter App](https://apps.apple.com/us/app/transporter/id1450874784) from the Mac App Store +2. Open it and sign in with your Apple ID +3. Click the + sign and select the `APP_NAME.pkg` file that you generated in the previous step. Upload it +4. Go back to the [App Store Connect](https://appstoreconnect.apple.com/apps) site and navigate back into your app submission. Select the version that you are ready to make available on the App Store. Under `Build` select the package that you uploaded via Transporter. + +That's it! You can now use the site to submit your App for review. After a few business days if all goes well you should see your App live on the Mac App Store. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx new file mode 100644 index 00000000000..dcf192d337f --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx @@ -0,0 +1,95 @@ +# Manual Builds + +The Wails CLI does a lot of heavy lifting for the project, but sometimes it's desirable to manually build your project. This document will discuss the different operations the CLI does and how this may be achieved in different ways. + +## Build Process + +When either `wails build` or `wails dev` are used, the Wails CLI performs a common build process: + + - Install frontend dependencies + - Build frontend project + - Generate build assets + - Compile application + - [optional] Compress application + +### Install frontend dependencies + +#### CLI Steps + +- If the `-s` flag is given, this step is skipped +- Checks `wails.json` to see if there is an install command in the key `frontend:install` +- If there isn't, it skips this step +- If there is, it checks if `package.json` exists in the frontend directory. If it doesn't exist, it skips this step +- An MD5 sum is generated from the `package.json` file contents +- It checks for the existence of `package.json.md5` and if it exists, will compare the contents of it (an MD5 sum) with the one generated to see if the contents have changed. If they are the same, this step is skipped +- If `package.json.md5` does not exist, it creates it using the generated MD5 sum +- If a build is now required, or `node_modules` does not exist, or the `-f` flag is given, the install command is executed in the frontend directory + +#### Manual Steps + +This step could be done from the command line or a script with `npm install`. + +### Build frontend project + +#### Wails CLI + +- If the `-s` flag is given, this step is skipped +- Checks `wails.json` to see if there is a build command in the key `frontend:build` +- If there isn't, it skips this step +- If there is, it is executed in the frontend directory + +#### Manual Steps + +This step could be done from the command line or a script with `npm run build` or whatever the frontend build script is. + +### Generate assets + +#### Wails CLI + +- If `-nopackage` flag is set, this stage is skipped +- If the `build/appicon.png` file does not exist, a default one is created +- For Windows, see [Bundling for Windows](#windows) +- If `build/windows/icon.ico` does not exist, it will create it from the `build/appicon.png` image. + +##### Windows + +- If `build/windows/icon.ico` does not exist, it will create it from `build/appicon.png` using icon sizes of 256, 128, 64, 48, 32 and 16. This is done using [winicon](https://github.com/leaanthony/winicon). +- If the `build/windows/.manifest` file does not exist, it creates it from a default version. +- Compiles the application as a production build (above) +- Uses [winres](https://github.com/tc-hib/winres) to bundle the icon and manifest into a `.syso` file ready for linking. + +#### Manual Steps + +- Create `icon.ico` using the [winicon](https://github.com/leaanthony/winicon) CLI tool (or any other tool). +- Create / Update a `.manifest` file for your application +- Use the [winres CLI](https://github.com/tc-hib/go-winres) to generate a `.syso` file. + +### Compile application + +#### Wails CLI + +- If the `-clean` flag is provided, the `build` directory is deleted and recreated +- For `wails dev`, the following default Go flags are used: `-tags dev -gcflags "all=-N -l"` +- For `wails build`, the following default Go flags are used: `-tags desktop,production -ldflags "-w -s"` + - On Windows, `-ldflags "-w -h -H windowsgui"` +- Additional tags passed to the CLI using `-tags` are added to the defaults +- Additional ldflags passed to the CLI using `-ldflags` are added to the defaults +- The `-o` flag is passed through +- The Go compiler specified by `-compiler` will be used for compilation + +#### Manual steps + +- For dev build, the minimum command would be: `go build -tags dev -gcflags "all=-N -l"` +- For production build, the minimum command would be: `go build -tags desktop,production -ldflags "-w -s -H windowsgui"` +- Ensure that you compile in the same directory as the `.syso` file + +### Compress application + +#### Wails CLI + +- If the `-upx` flag has been given, the `upx` program will be run to compress the application with the default settings +- If `-upxflags` is also passed, these flags are used instead of the default ones + +#### Manual steps + +- Run `upx [flags]` manually to compress the application. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx new file mode 100644 index 00000000000..7123cbe6b60 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx @@ -0,0 +1,191 @@ +# Migrating from v1 + +## Overview + +Wails v2 is a significant change from v1. This document aims to highlight the changes and the steps in migrating an existing project. + +### Creating the Application + +In v1, the main application is created using `wails.CreateApp`, bindings are added with `app.Bind`, then the application is run using `app.Run()`. + +Example: + +```go title="v1" + app := wails.CreateApp(&wails.AppConfig{ + Title: "MyApp", + Width: 1024, + Height: 768, + JS: js, + CSS: css, + Colour: "#131313", + }) + app.Bind(basic) + app.Run() +``` + +In v2, there is just a single method, `wails.Run()`, that accepts [application options](../reference/options.mdx#application-options). + +```go title="v2" + err := wails.Run(&options.App{ + Title: "MyApp", + Width: 800, + Height: 600, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + basic, + }, + }) +``` + +### Binding + +In v1, it was possible to bind both arbitrary functions and structs. In v2, this has been simplified to only binding structs. The struct instances that were previously passed to the `Bind()` method in v1, are now specified in the `Bind` field of the [application options](../reference/options.mdx#application-options): + +```go title="v1" + app := wails.CreateApp(/* options */) + app.Bind(basic) +``` + +```go title="v2" + err := wails.Run(&options.App{ + /* other options */ + Bind: []interface{}{ + basic, + }, + }) +``` + +In v1, bound methods were available to the frontend at `window.backend`. This has changed to `window.go`.`` + +### Application Lifecycle + +In v1, there were 2 special methods in a bound struct: `WailsInit()` and `WailsShutdown()`. These have been replaced with 3 lifecycle hooks as part of the [application options](../reference/options.mdx#application-options): + +- [OnStartup](../reference/options.mdx#onstartup) +- [OnShutdown](../reference/options.mdx#onshutdown) +- [OnDomReady](../reference/options.mdx#ondomready) + +Note: [OnDomReady](../reference/options.mdx#ondomready) replaces the `wails:ready` system event in v1. + +These methods can be standard functions, but a common practice is to have them part of a struct: + +```go title="v2" + basic := NewBasicApp() + err := wails.Run(&options.App{ + /* Other Options */ + OnStartup: basic.startup, + OnShutdown: basic.shutdown, + OnDomReady: basic.domready, + }) +... +type Basic struct { + ctx context.Context +} +func (b *Basic) startup(ctx context.Context) { + b.ctx = ctx +} +... +``` + +### Runtime + +The runtime in v2 is much richer than v1 with support for menus, window manipulation and better dialogs. The signature of the methods has changed slightly - please refer the the [Runtime Reference](../reference/runtime/intro.mdx). + +In v1, the [runtime](../reference/runtime/intro.mdx) was available via a struct passed to `WailsInit()`. In v2, the runtime has been moved out to its own package. Each method in the runtime takes the `context.Context` that is passed to the [OnStartup](../reference/options.mdx#onstartup) method. + +```go title="Runtime Example" +package main + +import "github.com/wailsapp/wails/v2/pkg/runtime" + +type Basic struct { + ctx context.Context +} + +// startup is called at application startup +func (a *App) startup(ctx context.Context) { + a.ctx = ctx + runtime.LogInfo(ctx, "Application Startup called!") +} + +``` + +### Assets + +The _biggest_ change in v2 is how assets are handled. + +In v1, assets were passed via 2 application options: + +- `JS` - The application's JavaScript +- `CSS` - The application's CSS + +This meant that the responsibility of generating a single JS and CSS file was on the developer. This essentially required the use of complicated packers such as webpack. + +In v2, Wails makes no assumptions about your frontend assets, just like a webserver. All of your application assets are passed to the application options as an `embed.FS`. + +**This means there is no requirement to bundle your assets, encode images as Base64 or attempt the dark art of bundler configuration to use custom fonts**. + +At startup, Wails will scan the given `embed.FS` for `index.html` and use its location as the root path for all the other application assets - just like a webserver would. + +Example: An application has the following project layout. All final assets are placed in the `frontend/dist` directory: + +```shell +. +├── build/ +├── frontend/ +│ └── dist/ +│ ├── index.html +│ ├── main.js +│ ├── main.css +│ └── logo.svg +├── main.go +└── wails.json +``` + +Those assets may be used by the application by simply creating an `embed.FS`: + +```go title="Assets Example" +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + err := wails.Run(&options.App{ + /* Other Options */ + AssetServer: &assetserver.Options{ + Assets: assets, + }, + }) +} +``` + +Of course, bundlers can be used if you wish to. The only requirement is to pass the final application assets directory to Wails using an `embed.FS` in the `Assets` key of the [application options](../reference/options.mdx#application-options). + +### Project Configuration + +In v1, the project configuration was stored in the `project.json` file in the project root. In v2, the project configuration is stored in the `wails.json` file in the project root. + +The format of the file is slightly different. Here is a comparison: + +

+ +| v1 | v2 | Notes | +| ------------------ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | name | | +| description | | Removed | +| author / name | author / name | | +| author / email | author / email | | +| version | version | | +| binaryname | outputfilename | Changed | +| frontend / dir | | Removed | +| frontend / install | frontend:install | Changed | +| frontend / build | frontend:build | Changed | +| frontend / bridge | | Removed | +| frontend / serve | | Removed | +| tags | | Removed | +| | wailsjsdir | The directory to generate wailsjs modules | +| | assetdir | The directory of the compiled frontend assets for `dev` mode. This is normally inferred and could be left empty. | +| | reloaddirs | Comma separated list of additional directories to watch for changes and to trigger reloads in `dev` mode. This is only needed for some more advanced asset configurations. | + +

diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx new file mode 100644 index 00000000000..1655b380018 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx @@ -0,0 +1,25 @@ +# Клавиши мыши + +Время выполнения кода Wails перехватывает щелчки мыши для определения необходимости изменения размера окна или перемещения окна. Был задан вопрос о том, как определить, когда произошел клик мышки, потому что `window.onclick` не сообщит о кнопках мыши. Следующий код показывает, как обнаружить клики мышкой: + +```javascript +window.addEventListener("mousedown", handleMouseButtonDown); + +function handleMouseButtonDown(event) { + if (event.button === 0) { + // left mouse button + } else if (event.button === 1) { + // middle mouse button + } else if (event.button === 2) { + // right mouse button + } else if (event.button === 3) { + // back mouse button + } else if (event.button === 4) { + // forward mouse button + } else { + // other mouse button + } +} +``` + +Источник: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx new file mode 100644 index 00000000000..8094a0324f1 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx @@ -0,0 +1,40 @@ +# Обфускация кода + +Wails поддерживает обфускацию вашего приложения с помощью [grable](https://github.com/burrowers/garble). + +Чтобы обфусцировать ваше приложение, вы можете добавить флаг `obfuscate` к команде `wails build`: + +```bash +wails build -obfuscated +``` + +Для изменения настроек обфускации, вы можете использовать флаг `garbleargs`: + +```bash +wails build -obfuscated -garbleargs "-literals -tiny -seed=myrandomseed" +``` + +These settings may be persisted in your [project config](../reference/project-config). + +## Как это работает + +При стандартной сборке, все привязанные методы доступны в фронтенде через переменную `window.go`. При вызове этих методов происходит вызов соответствущих методов в бекенде, для этого используется имя функции. При использовании обфускации, методы привязываются по ID, а не по имени. Привязки, сгенерированные в папке `wailsjs` используют эти ID для вызова метода в бекенде. + +:::note + +Чтобы убедиться, что ваше приложение будет работать в режиме обфускации, используйте сгенерированные в папке `wailsjs` привязки. + +::: + +## Example + +Импортирование метода "Greet" из биндинга: + +```js +import { Greet } from "../../wailsjs/go/main/App"; + +// snip +Greet("World"); +``` + +обеспечит корректную работу с включенным режимом обфускации, так как привязки будут сгенерированы заново, используя новый механизм вызова метода по ID. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx new file mode 100644 index 00000000000..915633d0cea --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx @@ -0,0 +1,10 @@ +# Overscroll + +[Overscroll](https://developer.mozilla.org/en-US/docs/Web/CSS/overscroll-behavior) - это "эффект отскоков", который иногда получается, когда вы прокручиваете за границы содержимого страницы. Это часто используется в мобильных приложениях. Это можно отключить с помощью CSS: + +```css +html { + height: 100%; + overflow: hidden; +} +``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx new file mode 100644 index 00000000000..acb1eb656d6 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx @@ -0,0 +1,47 @@ +# Маршрутизация + +Маршрутизация - это популярный способ переключения шаблонов в приложении. Эта страница предлагает некоторые рекомендации о том, как это сделать. + +## Vue + +Рекомендуемый подход к маршрутизации в Vue — [Hash Mode](https://next.router.vuejs.org/guide/essentials/history-mode.html#hash-mode): + +```js +import { createRouter, createWebHashHistory } from "vue-router"; + +const router = createRouter({ + history: createWebHashHistory(), + routes: [ + //... + ], +}); +``` + +## Angular + +Рекомендуемый подход к маршрутизации в Angular - [HashLocationStrategy](https://codecraft.tv/courses/angular/routing/routing-strategies#_hashlocationstrategy): + +```ts +RouterModule.forRoot(routes, { useHash: true }); +``` + +## React + +The recommended approach for routing in React is [HashRouter](https://reactrouter.com/en/main/router-components/hash-router): + +```jsx +import { HashRouter } from "react-router-dom"; + +ReactDOM.render( + + {/* The rest of your app goes here */} + + } exact /> + } /> + } /> + {/* more... */} + + , + root +); +``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx new file mode 100644 index 00000000000..4c7cf45ba99 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx @@ -0,0 +1,387 @@ +# Code Signing + +This is a guide on how you can sign your binaries generated with Wails on MacOS and Windows. The guide will target CI environments, more specifically GitHub Actions. + +## Windows + +First off you need a code signing certificate. If you do not already have one, Microsoft's info page lists some providers [here](https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/get-a-code-signing-certificate). Please note that an EV certificate is not required unless you need to write kernel-level software such as device drivers. For signing your Wails app, a standard code signing certificate will do just fine. + +It may be a good idea to check with your certificate provider how to sign your binaries on your local machine before targeting automated build systems, just so you know if there are any special requirements. For instance, [here](https://www.ssl.com/how-to/using-your-code-signing-certificate/) is SSL.com's code signing guide for Windows. If you know how to sign locally, it will be easier to troubleshoot any potential issues in a CI environment. For instance, SSL.com code signing certificates require the `/tr` flag for [SignTool.exe](https://docs.microsoft.com/en-us/windows/win32/seccrypto/signtool) while other providers may only need the `/t` flag for providing the timestamping server. Popular GitHub Actions for signing Windows binaries like [this one](https://github.com/Dana-Prajea/code-sign-action) does not support the `/tr` flag on SignTool.exe. Therefore this guide will focus on signing our app manually with PowerShell commands, but you can use actions like the [code-sign-action](https://github.com/Dana-Prajea/code-sign-action) Action if you prefer. + +First off, let's make sure we are able to build our Wails app in our GitHub CI. Here is a small workflow template: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend manually here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +Next we need to give the GitHub workflow access to our signing certificate. This is done by encoding your .pfx or .p12 certificate into a base64 string. To do this in PowerShell, you can use the following command assuming your certificate is called 'my-cert.p12': + +```PowerShell +certutil -encode .\my-cert.p12 my-cert-base64.txt +``` + +You should now have your .txt file with the base64 encoded certificate. It should start with _-----BEGIN CERTIFICATE-----_ and end with _-----END CERTIFICATE-----_. Now you need to make two action secrets on GitHub. Navigate to _Settings -> Secrets -> Actions_ and create the two following secrets: + +- **WIN_SIGNING_CERT** with the contents of your base64 encoded certificate text. +- **WIN_SIGNING_CERT_PASSWORD** with the contents of your certificate password. + +Now we're ready to implement the signing in our workflow using one of the two methods: + +### Method 1: signing with commands + +This method uses PowerShell commands to sign our app, and leaves you control over the entire signing process. + +After the `"Build Wails app"` step, we can add the following step to our workflow: + +```yaml +- name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd /t /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' + +``` + +This script creates a new directory for your certificate file, creates the certificate file from our base64 secret, converts it to a .pfx file, and finally signs the binary. The following variables needs to be replaced in the last line: + +- **signing algorithm**: usually sha256. +- **timestamping server**: URL to the timestamping server to use with your certificate. +- **path to binary**: path to the binary you want to sign. + +Given that our Wails config has `outputfilename` set to "app.exe" and that we have a certificate from SSL.com, this would be our workflow: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\app.exe + + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +### Method 2: automatically signing with Action + +It is possible to use a Windows code signing Action like [this](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate) one, but note it requires a SHA1 hash for the certificate and a certificate name. View an example of how to configure it on the Action's [marketplace](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate). + +--- + +## MacOS + +First off you need your code signing certificate from Apple. If you do not have one, a simple Google search will help you acquire one. Once you have your certificate, you need to export it and encode it to base64. [This tutorial](https://localazy.com/blog/how-to-automatically-sign-macos-apps-using-github-actions) shows you how to do that in an easy manner. Once you have exported your .p12 certificate file, you can encode it to base64 as seen in the tutorial with the following command: + +```bash +base64 Certificates.p12 | pbcopy +``` + +Now you're ready to create some GitHub project secrets, just as with Windows: + +- **APPLE_DEVELOPER_CERTIFICATE_P12_BASE64** with the contents of your newly copied base64 certificate. +- **APPLE_DEVELOPER_CERTIFICATE_PASSWORD** with the contents of your certificate password. +- **APPLE_PASSWORD** with the contents of an App-Specific password to your Apple-ID account which you can generate [here](https://appleid.apple.com/account/manage). + +Let's make sure we are able to build our Wails app in our GitHub Action workflow. Here is a small template: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +For code signing on macOS, [gon](https://github.com/mitchellh/gon) is a very handy tool for code signing and communicating with Apple servers, also written in Go, and will be used in this guide. + +After the `Build Wails app` step, add the following to the workflow: + +```yaml +- name: MacOS download gon for code signing and app notarization + if: matrix.platform == 'macos-latest' + run: | + brew install mitchellh/gon/gon +``` + +Now we need to configure some gon config files in our `build/darwin` directory: + +1. gon-sign.json: + +```json +{ + "source": ["./build/bin/app.app"], + "bundle_id": "app.myapp", + "apple_id": { + "username": "my-appleid@email.com", + "password": "@env:APPLE_PASSWORD" + }, + "sign": { + "application_identity": "Developer ID Application: My Name" + } +} +``` + +Where `source` is your Wails binary, `bundle_id` is your bundle ID, `apple_id` contains your Apple ID username and App-Specific password which you created earlier, and `sign.application_identity` is your identity which you can find by running the following command: + +```bash +security find-identity -v -p codesigning +``` + +2. entitlements.plist: + +```plist + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + + +``` + +In this file you configure the entitlements you need for you app, e.g. camera permissions if your app uses the camera. Read more about entitlements [here](https://developer.apple.com/documentation/bundleresources/entitlements). + +Make sure you have updated your `Info.plist` file with the same bundle ID as you entered in `gon-sign.json`. Here's an example `Info.plist` file: + +```plist + + + CFBundlePackageTypeAPPL + CFBundleNameMyApp + CFBundleExecutableapp + CFBundleIdentifierapp.myapp + CFBundleVersion0.1.0 + CFBundleGetInfoStringMy app is cool and nice and chill and + CFBundleShortVersionString0.1.0 + CFBundleIconFileiconfile + LSMinimumSystemVersion10.13.0 + NSHighResolutionCapabletrue + LSApplicationCategoryTypepublic.app-category.utilities + NSHumanReadableCopyright© Me + +``` + +Now we're ready to add the signing step in our workflow after building the Wails app: + +```yaml +- name: Import Code-Signing Certificates for macOS + if: matrix.platform == 'macos-latest' + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} +- name: Sign our macOS binary + if: matrix.platform == 'macos-latest' + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json +``` + +Please note that signing binaries with Apple could take anywhere from minutes to hours. + +## Combined workflow file: + +Here is our GitHub workflow file with Windows + macOS combined: + +```yaml +name: "example combined" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: MacOS download gon for code signing and app notarization + if: matrix.platform == 'macos-latest' + run: | + brew install mitchellh/gon/gon + - name: Import Code-Signing Certificates for macOS + if: matrix.platform == 'macos-latest' + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} + - name: Sign our macOS binary + if: matrix.platform == 'macos-latest' + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json + - name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\Monitor.exe + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +# End notes + +This guide inspired by the RiftShare project and its workflow, which is highly recommended to check out [here](https://github.com/achhabra2/riftshare/blob/main/.github/workflows/build.yaml). diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx new file mode 100644 index 00000000000..dc7706f8ffa --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx @@ -0,0 +1,81 @@ +# Single Instance Lock + +Single instance lock is a mechanism that allows you to prevent multiple instances of your app from running at the same time. +It is useful for apps that are designed to open files from the command line or from the OS file explorer. + +## Important + +Single Instance Lock does not implement a secure communications protocol between instances. When using single instance lock, +your app should treat any data passed to it from second instance callback as untrusted. +You should verify that args that you receive are valid and don't contain any malicious data. + +## How it works + +Windows: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via a shared window using [SendMessage](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage) +macOS: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via [NSDistributedNotificationCenter](https://developer.apple.com/documentation/foundation/nsdistributednotificationcenter) +Linux: Single instance lock is implemented using [dbus](https://www.freedesktop.org/wiki/Software/dbus/). The dbus name is generated from the unique id that you provide. Data is passed to the first instance via [dbus](https://www.freedesktop.org/wiki/Software/dbus/) + +## Usage + +When creating your app, you can enable single instance lock by passing a `SingleInstanceLock` struct to the `App` struct. +Use the `UniqueId` field to specify a unique id for your app. +This id is used to generate the mutex name on Windows and macOS and the dbus name on Linux. Use a UUID to ensure that the id is unique. +The `OnSecondInstanceLaunch` field is used to specify a callback that is called when a second instance of your app is launched. +The callback receives a `SecondInstanceData` struct that contains the command line arguments passed to the second instance and the working directory of the second instance. + +Note that OnSecondInstanceLaunch don't trigger windows focus. +You need to call `runtime.WindowUnminimise` and `runtime.Show` to bring your app to the front. +Note that on linux systems window managers may prevent your app from being brought to the front to avoid stealing focus. + +```go title="main.go" +var wailsContext *context.Context + +// NewApp creates a new App application struct +func NewApp() *App { + return &App{} +} + +// startup is called when the app starts. The context is saved +// so we can call the runtime methods +func (a *App) startup(ctx context.Context) { + wailsContext = &ctx +} + +func (a *App) onSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) { + secondInstanceArgs = secondInstanceData.Args + + println("user opened second instance", strings.Join(secondInstanceData.Args, ",")) + println("user opened second from", secondInstanceData.WorkingDirectory) + runtime.WindowUnminimise(*wailsContext) + runtime.Show(*wailsContext) + go runtime.EventsEmit(*wailsContext, "launchArgs", secondInstanceArgs) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + OnStartup: app.startup, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx new file mode 100644 index 00000000000..4651c422ed1 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx @@ -0,0 +1,153 @@ +# SvelteKit + +This guide will go into: + +1. Miminal Installation Steps - The steps needed to get a minimum Wails setup working for SvelteKit. +2. Install Script - Bash script for accomplishing the Minimal Installation Steps with optional Wails branding. +3. Important Notes - Issues that can be encountered when using SvelteKit + Wails and fixes. + +## 1. Minimal Installation Steps + +##### Install Wails for Svelte. + +- `wails init -n myapp -t svelte` + +##### Delete the svelte frontend. + +- Navigate into your newly created myapp folder. +- Delete the folder named "frontend" + +##### While in the Wails project root. Use your favorite package manager and install SvelteKit as the new frontend. Follow the prompts. + +- `npm create svelte@latest frontend` + +##### Modify wails.json. + +- Add `"wailsjsdir": "./frontend/src/lib",` Do note that this is where your Go and runtime functions will appear. +- Change your package manager frontend here if not using npm. + +##### Modify main.go. + +- The first comment `//go:embed all:frontend/dist` needs to be changed to `//go:embed all:frontend/build` + +##### Install/remove dependencies using your favorite package manager. + +- Navigate into your "frontend" folder. +- `npm i` +- `npm uninstall @sveltejs/adapter-auto` +- `npm i -D @sveltejs/adapter-static` + +##### Change adapter in svelte.config.js + +- First line of file change `import adapter from '@sveltejs/adapter-auto';` to `import adapter from '@sveltejs/adapter-static';` + +##### Put SvelteKit into SPA mode with prerendering. + +- Create a file under myapp/frontend/src/routes/ named +layout.ts/+layout.js. +- Add two lines into the newly created file `export const prerender = true` and `export const ssr = false` + +##### Test installation. + +- Navigate back into the Wails project root (one directory up). +- run `wails dev` +- If the application doesn't run please check through the previous steps. + +## 2. Install Script + +##### This Bash Script does the steps listed above. Make sure to read over the script and understand what the script is doing on your computer. + +- Create a file sveltekit-wails.sh +- Copy the below code into the new file then save it. +- Make it executable with `chmod +x sveltekit-wails.sh` +- Brand is an optional param below that adds back in the wails branding. Leave third param blank to not insert the Wails branding. +- Example usage: `./sveltekit-wails.sh pnpm newapp brand` + +##### sveltekit-wails.sh: + +``` +manager=$1 +project=$2 +brand=$3 +wails init -n $project -t svelte +cd $project +sed -i "s|npm|$manager|g" wails.json +sed -i 's|"auto",|"auto",\n "wailsjsdir": "./frontend/src/lib",|' wails.json +sed -i "s|all:frontend/dist|all:frontend/build|" main.go +if [[ -n $brand ]]; then + mv frontend/src/App.svelte +page.svelte + sed -i "s|'./assets|'\$lib/assets|" +page.svelte + sed -i "s|'../wails|'\$lib/wails|" +page.svelte + mv frontend/src/assets . +fi +rm -r frontend +$manager create svelte@latest frontend +if [[ -n $brand ]]; then + mv +page.svelte frontend/src/routes/+page.svelte + mkdir frontend/src/lib + mv assets frontend/src/lib/ +fi +cd frontend +$manager i +$manager uninstall @sveltejs/adapter-auto +$manager i -D @sveltejs/adapter-static +echo -e "export const prerender = true\nexport const ssr = false" > src/routes/+layout.ts +sed -i "s|-auto';|-static';|" svelte.config.js +cd .. +wails dev +``` + +## 3. Important Notes + +##### Server files will cause build failures. + +- \+layout.server.ts, +page.server.ts, +server.ts or any file with "server" in the name will fail to build as all routes are prerendered. + +##### The Wails runtime unloads with full page navigations! + +- Anything that causes full page navigations: `window.location.href = '//'` or Context menu reload when using wails dev. What this means is that you can end up losing the ability to call any runtime breaking the app. There are two ways to work around this. +- Use `import { goto } from '$app/navigation'` then call `goto('//')` in your +page.svelte. This will prevent a full page navigation. +- If full page navigation can't be prevented the Wails runtime can be added to all pages by adding the below into the `` of myapp/frontend/src/app.html + +``` + +... + + + +... + +``` + +See https://wails.io/docs/guides/frontend for more information. + +##### Inital data can be loaded and refreshed from +page.ts/+page.js to +page.svelte. + +- \+page.ts/+page.js works well with load() https://kit.svelte.dev/docs/load#page-data +- invalidateAll() in +page.svelte will call load() from +page.ts/+page.js https://kit.svelte.dev/docs/load#rerunning-load-functions-manual-invalidation. + +##### Error Handling + +- Expected errors using Throw error works in +page.ts/+page.js with a +error.svelte page. https://kit.svelte.dev/docs/errors#expected-errors +- Unexpected errors will cause the application to become unusable. Only recovery option (known so far) from unexpected errors is to reload the app. To do this create a file myapp/frontend/src/hooks.client.ts then add the below code to the file. + +``` +import { WindowReloadApp } from '$lib/wailsjs/runtime/runtime' +export async function handleError() { + WindowReloadApp() +} +``` + +##### Using Forms and handling functions + +- The simplest way is to call a function from the form is the standard, bind:value your variables and prevent submission `` +- The more advanced way is to use:enhance (progressive enhancement) which will allow for convenient access to formData, formElement, submitter. The important note is to always cancel() the form which prevents server side behavior. https://kit.svelte.dev/docs/form-actions#progressive-enhancement Example: + +``` + { + cancel() + console.log(Object.fromEntries(formData)) + console.log(formElement) + console.log(submitter) + handle() +}}> +``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx new file mode 100644 index 00000000000..23e24c4c8dc --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx @@ -0,0 +1,97 @@ +# Templates + +Wails генерирует проекты из заранее созданных шаблонов. В v1 это было трудно поддерживать набор проектов, которые были подвержены устареванию. В v2 для расширения прав и возможностей сообщества добавлено несколько новых возможностей для шаблонов: + +- Возможность создания проектов из [удаленных шаблонов](../reference/cli.mdx#remote-templates) +- Инструменты, которые помогут создать собственные шаблоны + +## Создание шаблонов + +Для создания шаблона вы можете использовать команду `wails generate template`. Для создания шаблона по умолчанию запустите: + +`wails generate template -name mytemplate` + +Это создает каталог "mytemplate" с файлами по умолчанию: + +```shell title=mytemplate/ +. +|-- NEXTSTEPS.md +|-- README.md +|-- app.tmpl.go +|-- frontend +| `-- dist +| |-- assets +| | |-- fonts +| | | |-- OFL.txt +| | | `-- nunito-v16-latin-regular.woff2 +| | `-- images +| | `-- logo-dark.svg +| |-- index.html +| |-- main.css +| `-- main.js +|-- go.mod.tmpl +|-- main.tmpl.go +|-- template.json +`-- wails.tmpl.json +``` + +### Обзор шаблона + +Шаблон по умолчанию состоит из следующих файлов и директорий: + +| Имя файла / Каталог | Описание | +| ------------------- | ------------------------------------ | +| NEXTSTEPS.md | Инструкции по заполнению шаблона | +| README.md | README публикуемый с шаблоном | +| app.tmpl.go | `app.go` файл шаблона | +| frontend/ | Каталог, содержащий файлы интерфейса | +| go.mod.tmpl | `go.mod` файл шаблона | +| main.tmpl.go | `main.go` файл шаблона | +| template.json | Метаданные шаблона | +| wails.tmpl.json | `wails.json` файл шаблона | + +На данный момент желательно выполнить шаги в `NEXTSTEPS.md`. + +## Создать шаблон из существующего проекта + +Можно создать шаблон из существующего проекта фронтенда, передав путь к проекту при генерации шаблона. Теперь мы рассмотрим как создать шаблон Vue 3: + +- Установите vue cli: `npm install -g @vue/cli` +- Создайте проект по умолчанию: `vue create vue3-base` + - Выберите `Default (Vue 3) ([Vue 3] babel, eslint)` +- После создания проекта, выполните: + +```shell +> wails generate template -name wails-vue3-template -frontend .\vue3-base\ +Extracting base template files... +Migrating existing project files to frontend directory... +Updating package.json data... +Renaming package.json -> package.tmpl.json... +Updating package-lock.json data... +Renaming package-lock.json -> package-lock.tmpl.json... +``` + +- Шаблон теперь может быть настроен как указано в файле `NEXTSTEPS.md` +- Как только файлы будут готовы, их можно протестировать, запустив: `wails init -n my-vue3-project -t .\wails-vue3-template\` +- Для тестирования нового проекта выполните: `cd my-vue3-project` затем `wails build` +- Как только проект будет скомпилирован, запустите его: `.\build\bin\my-vue3-project.exe` +- У вас должно получиться полностью работающее приложение Vue3: + +```mdx-code-block +
+ +
+``` + +## Публикация шаблона + +Для публикации шаблона просто загрузите файлы на GitHub. Поощряется следующая лучшая практика: + +- Удалите любые нежелательные файлы и каталоги (например, `.git`) из вашей frontend директории +- Убедитесь, что `template.json` завершен, особенно `helpurl` +- Отправить файлы на GitHub +- Создайте PR на странице [Шаблоны сообщества](../community/templates.mdx) +- Расскажите о своем шаблоне на [Template Announcement](https://github.com/wailsapp/wails/discussions/825) форуме diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx new file mode 100644 index 00000000000..1c3b6a9cc52 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx @@ -0,0 +1,368 @@ +# Troubleshooting + +An assortment of troubleshooting tips. + +## The `wails` command appears to be missing? + +If your system is reporting that the `wails` command is missing, make sure you have followed the Go installation guide correctly. Normally, it means that the `go/bin` directory in your User's home directory is not in the `PATH` environment variable. You will also normally need to close and reopen any open command prompts so that changes to the environment made by the installer are reflected at the command prompt. + +## My application is displaying a white/blank screen + +Check that your application includes the assets from the correct directory. In your `main.go` file, you will have something similar to the following code: + +```go +//go:embed all:frontend/dist +var assets embed.FS +``` + +Check that `frontend/dist` contains your application assets. + +### Mac + +If this happens on Mac, try adding the following to your `Info.plist`: + +```xml +NSAppTransportSecurity + + NSAllowsLocalNetworking + + +``` + +Reference: https://github.com/wailsapp/wails/issues/1504#issuecomment-1174317433 + +## Mac application not valid + +If your built application looks like this in finder: + +```mdx-code-block +

+ +

+``` + +it's likely that your application's `info.plist` is invalid. Update the file in `build/.app/Contents/info.plist` and check if the data is valid, EG check the binary name is correct. To persist the changes, copy the file back to the `build/darwin` directory. + +## My application is not displaying the correct icon in Windows Explorer + +If your application is not displaying the correct icon, try deleting the hidden `IconCache.db` file located in the `C:\Users\<your username>\AppData\Local` directory. This will force Windows to rebuild the icon cache. + +Source: https://github.com/wailsapp/wails/issues/2360#issuecomment-1556070036 + +## Cannot call backend method from frontend with variadic arguments + +If you have a backend method defined with variadic parameters, eg: + +```go +func (a *App) TestFunc(msg string, args ...interface{}) error { + // Code +} +``` + +calling this method from the frontend like this will fail: + +```js +var msg = "Hello: "; +var args = ["Go", "JS"]; +window.go.main.App.TestFunc(msg, ...args) + .then((result) => { + //do things here + }) + .catch((error) => { + //handle error + }); +``` + +Workaround: + +```js +var msg = "Hello "; +var args = ["Go", "JS"]; +window.go.main.App.TestFunc(msg, args) + .then((result) => { + //without the 3 dots + //do things here + }) + .catch((error) => { + //handle error + }); +``` + +Credit: https://github.com/wailsapp/wails/issues/1186 + +## I'm having getting proxy errors when trying to install Wails + +If you are getting errors like this: + +``` +"https://proxy.golang.org/github.com/wailsapp/wails/cmd/wails/@v/list": dial tcp 172.217.163.49:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. +``` + +it's probably because the official Go Proxy is being blocked (Users in China have reported this). The solution is to set up the proxy manually, eg: + +``` +go env -w GO111MODULE=on +go env -w GOPROXY=https://goproxy.cn,direct +``` + +Source: https://github.com/wailsapp/wails/issues/1233 + +## The generated TypeScript doesn't have the correct types + +Sometimes the generated TypeScript doesn't have the correct types. To mitigate this, it is possible to specify what types should be generated using the `ts_type` struct tag. For more details, please read [this](https://github.com/tkrajina/typescriptify-golang-structs#custom-types). + +## When I navigate away from `index.html`, I am unable to call methods on the frontend + +If you navigate away from `index.html` to a new html file, the context will be lost. This can be fixed by adding the following imports to the `` section of any new page you navigate to: + +```html + + + + +``` + +Source: https://github.com/wailsapp/wails/discussions/1512 + +## I get `too many open files` errors on my Mac when I run `wails dev` + +By default, macOS will only allow you to open a maximum of 256 files. This can affect the `wails dev` command. This limit can be increased by running: `ulimit -n 1024` in the terminal. + +FSNotify is [looking to move to Apple's fsevents](https://github.com/fsnotify/fsnotify/issues/11) for Mac. If this isn't completed soon, we will create our own implementation, tracked [here](https://github.com/wailsapp/wails/issues/1733). + +## My Mac app gives me weird compilation errors + +A few users have reported seeing compilation errors such as the following: + +```shell +# github.com/wailsapp/wails/v2/internal/frontend/desktop/darwin +In file included from ../../pkg/mod/github.com/wailsapp/wails/v2@v2.0.0-beta.44.2/internal/frontend/desktop/darwin/callbacks.go:9: +In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:12: +/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSBundle.h:91:143: error: function does not return NSString +- (NSAttributedString *)localizedAttributedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName NS_FORMAT_ARGUMENT(1) NS_REFINED_FOR_SWIFT API_AVAILABLE(macos(12.0), ios(15.0), watchos(8.0), tvos(15.0)); + ~~~~~~~~~~~~~~ ^ ~ +/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:103:48: note: expanded from macro 'NS_FORMAT_ARGUMENT' + #define NS_FORMAT_ARGUMENT(A) __attribute__ ((format_arg(A))) +``` + +This is _normally_ due to a mismatch with the OS version you are running and the version of the XCode Command Line Tools installed. If you see an error like this, try upgrading your XCode Command Line Tools to the latest version. + +If reinstalling Xcode Command Tools still fails, you can check the path where the toolkit is located using: + +`xcode-select -p` + +If `/Applications/Xcode.app/Contents/Developer` is displayed, run `sudo xcode-select --switch /Library/Developer/CommandLineTools` + +Sources: https://github.com/wailsapp/wails/issues/1806 and https://github.com/wailsapp/wails/issues/1140#issuecomment-1290446496 + +## My application won't compile on Mac + +If you are getting errors like this: + +```shell +l1@m2 GoEasyDesigner % go build -tags dev -gcflags "all=-N -l" +/Users/l1/sdk/go1.20.5/pkg/tool/darwin_arm64/link: running clang failed: exit status 1 +Undefined symbols for architecture arm64: + "_OBJC_CLASS_$_UTType", referenced from: + objc-class-ref in 000016.o +ld: symbol(s) not found for architecture arm64 +clang: error: linker command failed with exit code 1 (use -v to see invocation) +``` +Ensure you have the latest SDK installed. If so and you're still experiencing this issue, try the following: + +```shell +export CGO_LDFLAGS="-framework UniformTypeIdentifiers" && go build -tags dev -gcflags "all=-N -l" +``` + +Sources: https://github.com/wailsapp/wails/pull/2925#issuecomment-1726828562 + + +-- + +## Cannot start service: Host version "x.x.x does not match binary version "x.x.x" + +It's preferable to add `frontend/node_modules` and `frontend/package-lock.json` to your `.gitignore`. Otherwise when opening your repository on another machine that may have different versions of Node installed, you may not be able to run your application. + +If this does happen, simply delete `frontend/node_modules` and `frontend/package-lock.json` and run your `wails build` or `wails dev` command again. + +## Build process stuck on "Generating bindings" + +Bindings generation process runs your application in a special mode. If application, intentionally or unintentionally, contains an endless loop (i.e. not exiting after `wails.Run()` finished), this can lead to build process stuck on the stage of bindings generation. Please make sure your code exits properly. + +## Mac application flashes white at startup + +This is due to the default background of the webview being white. If you want to use the window background colour instead, you can make the webview background transparent using the following config: + +```go + err := wails.Run(&options.App{ + Title: "macflash", + Width: 1024, + Height: 768, + // Other settings + Mac: &mac.Options{ + WebviewIsTransparent: true, + }, + }) +``` + +## I get a "Microsoft Edge can't read or write to its data directory" error when running my program as admin on Windows + +You set your program to require admin permissions and it worked great! Unfortunately, some users are seeing a "Microsoft Edge can't read or write to its data directory" error when running it. + +When a Windows machine has two local accounts: + +- Alice, an admin +- Bob, a regular user + +Bob sees a UAC prompt when running your program. Bob enters Alice's admin credentials into this prompt. The app launches with admin permissions under Alice's account. + +Wails instructs WebView2 to store user data at the specified `WebviewUserDataPath`. It defaults to `%APPDATA%\[BinaryName.exe]`. + +Because the application is running under Alice's account, `%APPDATA%\[BinaryName.exe]` resolves to `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`. + +WebView2 [creates some child processes under Bob's logged-in account instead of Alice's admin account](https://github.com/MicrosoftEdge/WebView2Feedback/issues/932#issue-807464179). Since Bob cannot access `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`, the "Microsoft Edge can't read or write to its data directory" error is shown. + +Possible solution #1: + +Refactor your application to work without constant admin permissions. If you just need to perform a small set of admin tasks (such as running an updater), you can run your application with the minimum permissions and then use the `runas` command to run these tasks with admin permissions as needed: + +```go +//go:build windows + +package sample + +import ( + "golang.org/x/sys/windows" + "syscall" +) + +// Calling RunAs("C:\path\to\my\updater.exe") shows Bob a UAC prompt. Bob enters Alice's admin credentials. The updater launches with admin permissions under Alice's account. +func RunAs(path string) error { + verbPtr, _ := syscall.UTF16PtrFromString("runas") + exePtr, _ := syscall.UTF16PtrFromString(path) + cwdPtr, _ := syscall.UTF16PtrFromString("") + argPtr, _ := syscall.UTF16PtrFromString("") + + var showCmd int32 = 1 //SW_NORMAL + + err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd) + if err != nil { + return err + } + return nil +} +``` + +Possible solution #2: + +Run your application with extended permissions. If you absolutely must run with constant admin permissions, WebView2 will function correctly if you use a data directory accessible by both users and you also launch your app with the `SeBackupPrivilege`, `SeDebugPrivilege`, and `SeRestorePrivilege` permissions. Here's an example: + +```go +package main + +import ( + "embed" + "os" + "runtime" + + "github.com/fourcorelabs/wintoken" + "github.com/hectane/go-acl" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +//go:embed all:frontend/dist +var assets embed.FS + +const ( + fixedTokenKey = "SAMPLE_RANDOM_KEY" + fixedTokenVal = "with-fixed-token" + webviewDir = "C:\\ProgramData\\Sample" +) + +func runWithFixedToken() { + println("Re-launching self") + token, err := wintoken.OpenProcessToken(0, wintoken.TokenPrimary) //pass 0 for own process + if err != nil { + panic(err) + } + defer token.Close() + + token.EnableTokenPrivileges([]string{ + "SeBackupPrivilege", + "SeDebugPrivilege", + "SeRestorePrivilege", + }) + + cmd := exec.Command(os.Args[0]) + cmd.Args = os.Args + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", fixedTokenKey, fixedTokenVal)) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.SysProcAttr = &syscall.SysProcAttr{Token: syscall.Token(token.Token())} + if err := cmd.Run(); err != nil { + println("Error after launching self:", err) + os.Exit(1) + } + println("Clean self launch :)") + os.Exit(0) +} + +func main() { + if runtime.GOOS == "windows" && os.Getenv(fixedTokenKey) != fixedTokenVal { + runWithFixedToken() + } + + println("Setting data dir to", webviewDir) + if err := os.MkdirAll(webviewDir, os.ModePerm); err != nil { + println("Failed creating dir:", err) + } + if err := acl.Chmod(webviewDir, 0777); err != nil { + println("Failed setting ACL on dir:", err) + } + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "sample-data-dir", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + Windows: &windows.Options{ + WebviewUserDataPath: webviewDir, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +If you use a data directory accessible by both users but not the extended privileges, you will receive a WebView2 `80010108 The object invoked has disconnected from its clients` error. + +Possible future solution #3: [run WebView2 using an in-memory mode if implemented](https://github.com/MicrosoftEdge/WebView2Feedback/issues/3637#issuecomment-1728300982). + +## WebView2 installation succeeded, but the wails doctor command shows that it is not installed + +If you have installed WebView2, but the `wails doctor` command shows that it is not installed, it is likely that the WebView2 runtime installed was for a different architecture. You can download the correct runtime from [here](https://developer.microsoft.com/en-us/microsoft-edge/webview2/). + +Source: https://github.com/wailsapp/wails/issues/2917 + +## WebVie2wProcess failed with kind + +If your Windows app generates this kind of error, you can check out what the error means [here](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2processfailedkind?view=webview2-winrt-1.0.2045.28). + diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx new file mode 100644 index 00000000000..539c52ba582 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx @@ -0,0 +1,82 @@ + +# Visual Studio Code + +Эта страница предназначена для разных советов и трюков при использовании Visual Studio Code с Wails. + +## Конфигурация Vetur + +Большое спасибо [@Lyimmi](https://github.com/Lyimmi) за этот совет. Изначально оставил сообщение [здесь](https://github.com/wailsapp/wails/issues/1791#issuecomment-1228158349). + +Vetur - это популярный плагин для кода Visual Studio, который предоставляет подсветку синтаксиса и завершение кода для Vue проектов. При загрузке проекта Wails в VSCode, Ветур выбросит ошибку, ожидая найти проект фронтенда в корневом каталоге. Чтобы исправить это, можно сделать следующее: + +Создайте файл `vetur.config.js` в корне проекта. + +```javascript +// vetur.config.js +/** @type {import('vls').VeturConfig} */ +module.exports = { + // **optional** default: `{}` + // override vscode settings + // Notice: It only affects the settings used by Vetur. + settings: { + "vetur.useWorkspaceDependencies": true, + "vetur.experimental.templateInterpolationService": true + }, + // **optional** default: `[{ root: './' }]` + // support monorepos + projects: [ + { + // **required** + // Where is your project? + // It is relative to `vetur.config.js`. + // root: './packages/repo1', + root: './frontend', + // **optional** default: `'package.json'` + // Where is `package.json` in the project? + // We use it to determine the version of vue. + // It is relative to root property. + package: './package.json', + // **optional** + // Where is TypeScript config file in the project? + // It is relative to root property. + tsconfig: './tsconfig.json', + // **optional** default: `'./.vscode/vetur/snippets'` + // Where is vetur custom snippets folders? + snippetFolder: './.vscode/vetur/snippets', + // **optional** default: `[]` + // Register globally Vue component glob. + // If you set it, you can get completion by that components. + // It is relative to root property. + // Notice: It won't actually do it. You need to use `require.context` or `Vue.component` + globalComponents: [ + './src/components/**/*.vue' + ] + } + ] +} +``` + +Затем настройте `frontend/tsconfig.json`: + +```javascript +{ + "compilerOptions": { + "module": "system", + "noImplicitAny": true, + "removeComments": true, + "preserveConstEnums": true, + "sourceMap": true, + "outFile": "../../built/local/tsc.js", + "allowJs": true + }, + "exclude": [ + "node_modules", + "**/*.spec.ts" + ], + "include": [ + "src/**/*", + "wailsjs/**/*.ts" + ] +} +``` +Это должно позволить теперь использовать Vetur как ожидалось. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx new file mode 100644 index 00000000000..b332c5f1dc0 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx @@ -0,0 +1,58 @@ +# NSIS installer + +```mdx-code-block +

+ +
+

+``` + +Wails supports generating Windows installers using the [NSIS installer](https://nsis.sourceforge.io/). + +## Installing NSIS + +### Windows + +The installer is available on the [NSIS Download](https://nsis.sourceforge.io/Download) page. + +If you use the chocolatey package manager, run the following script: + +``` +choco install nsis +``` + +If you install NSIS manually, you need to add the _Bin_ folder, which contains `makensis.exe`, in your NSIS installation to your path. [Here](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/) is a good tutorial on how to add to path on Windows. + +### Linux + +Пакет `nsis` должен быть доступен через менеджер пакетов вашего дистрибутива. + +### MacOS + +NSIS is available to install through homebrew: `brew install nsis`. + +## Generating the installer + +When a new project is created, Wails generates the NSIS configuration files in `build/windows/installer`. The config data is read from `installer/info.json` and that is configured to use the project's `wails.json` Info section: + +```json +// ... + "Info": { + "companyName": "My Company Name", + "productName": "Wails Vite", + "productVersion": "1.0.0", + "copyright": "Copyright.........", + "comments": "Built using Wails (https://wails.io)" + }, +``` + +To generate an installer for your application, use the `-nsis` flag with `wails build`: + +``` +wails build -nsis +``` + +The installer will now be available in the `build/bin` directory. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx new file mode 100644 index 00000000000..821808c0b8d --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx @@ -0,0 +1,61 @@ +# Windows + +This page has miscellaneous guides related to developing Wails applications for Windows. + +## Handling the WebView2 Runtime Dependency + +Wails applications built for Windows have a runtime requirement on the Microsoft [WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/). Windows 11 will have this installed by default, but some machines won't. Wails offers an easy approach to dealing with this dependency. + +By using the `-webview2` flag when building, you can decide what your application will do when a suitable runtime is not detected (including if the installed runtime is too old). The four options are: + +1. Download +2. Embed +3. Browser +4. Error + +### Download + +This option will prompt the user that no suitable runtime has been found and then offer to download and run the official bootstrapper from Microsoft's WebView2 site. If the user proceeds, the official bootstrapper will be downloaded and run. + +### Embed + +This option embeds the official bootstrapper within the application. If no suitable runtime has been found, the application will offer to run the bootstrapper. This adds ~150k to the binary size. + +### Browser + +This option will prompt the user that no suitable runtime has been found and then offer to open a browser to the official WebView2 page where the bootstrapper can be downloaded and installed. The application will then exit, leaving the installation up to the user. + +### Error + +If no suitable runtime is found, an error is given to the user and no further action taken. + +## Fixed version runtime + +Another way of dealing with webview2 dependency is shipping it yourself. You can download [fixed version runtime](https://developer.microsoft.com/microsoft-edge/webview2/#download-section) and bundle or download it with your application. + +Also, you should specify path to fixed version of webview2 runtime in the `windows.Options` structure when launching wails. + +```go + wails.Run(&options.App{ + Windows: &windows.Options{ + WebviewBrowserPath: "", + }, + }) +``` + +Note: When `WebviewBrowserPath` is specified, `error` strategy will be forced in case of minimal required version mismatch or invalid path to a runtime. + +## Spawning other programs + +When spawning other programs, such as scripts, you will see the window appear on the screen. To hide the window, you can use the following code: + +```go +cmd := exec.Command("your_script.exe") +cmd.SysProcAttr = &syscall.SysProcAttr{ + HideWindow: true, + CreationFlags: 0x08000000, +} +cmd.Start() +``` + +Solution provided by [sithembiso](https://github.com/sithembiso) on the [discussions board](https://github.com/wailsapp/wails/discussions/1734#discussioncomment-3386172). diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx new file mode 100644 index 00000000000..44fa130cc74 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx @@ -0,0 +1,369 @@ +--- +sidebar_position: 20 +--- + +# How does it work? + +A Wails application is a standard Go application, with a webkit frontend. The Go part of the application consists of the application code and a runtime library that provides a number of useful operations, like controlling the application window. The frontend is a webkit window that will display the frontend assets. Also available to the frontend is a JavaScript version of the runtime library. Finally, it is possible to bind Go methods to the frontend, and these will appear as JavaScript methods that can be called, just as if they were local JavaScript methods. + +```mdx-code-block +
+ +
+``` + +## The Main Application + +### Overview + +The main application consists of a single call to `wails.Run()`. It accepts the application configuration which describes the size of the application window, the window title, what assets to use, etc. A basic application might look like this: + +```go title="main.go" +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + + app := &App{} + + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + + +type App struct { + ctx context.Context +} + +func (b *App) startup(ctx context.Context) { + b.ctx = ctx +} + +func (b *App) shutdown(ctx context.Context) {} + +func (b *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +### Options rundown + +This example has the following options set: + +- `Title` - The text that should appear in the window's title bar +- `Width` & `Height` - The dimensions of the window +- `Assets` - The application's frontend assets +- `OnStartup` - A callback for when the window is created and is about to start loading the frontend assets +- `OnShutdown` - A callback for when the application is about to quit +- `Bind` - A slice of struct instances that we wish to expose to the frontend + +A full list of application options can be found in the [Options Reference](reference/options). + +#### Assets + +The `Assets` option is mandatory as you can't have a Wails application without frontend assets. Those assets can be any files you would expect to find in a web application - html, js, css, svg, png, etc. **There is no requirement to generate asset bundles** - plain files will do. When the application starts, it will attempt to load `index.html` from your assets and the frontend will essentially work as a browser from that point on. It is worth noting that there is no requirement on where in the `embed.FS` the files live. It is likely that the embed path uses a nested directory relative to your main application code, such as `frontend/dist`: + +```go title="main.go" +//go:embed all:frontend/dist +var assets embed.FS +``` + +At startup, Wails will iterate the embedded files looking for the directory containing `index.html`. All other assets will be loaded relative to this directory. + +As production binaries use the files contained in `embed.FS`, there are no external files required to be shipped with the application. + +When running in development mode using the `wails dev` command, the assets are loaded off disk, and any changes result in a "live reload". The location of the assets will be inferred from the `embed.FS`. + +More details can be found in the [Application Development Guide](guides/application-development.mdx). + +#### Application Lifecycle Callbacks + +Just before the frontend is about to load `index.html`, a callback is made to the function provided in [OnStartup](reference/options.mdx#onstartup). A standard Go context is passed to this method. This context is required when calling the runtime so a standard pattern is to save a reference to in this method. Just before the application shuts down, the [OnShutdown](reference/options.mdx#onshutdown) callback is called in the same way, again with the context. There is also an [OnDomReady](reference/options.mdx#ondomready) callback for when the frontend has completed loading all assets in `index.html` and is equivalent of the [`body onload`](https://www.w3schools.com/jsref/event_onload.asp) event in JavaScript. It is also possible to hook into the window close (or application quit) event by setting the option [OnBeforeClose](reference/options.mdx#onbeforeclose). + +#### Method Binding + +The `Bind` option is one of the most important options in a Wails application. It specifies which struct methods to expose to the frontend. Think of structs like "controllers" in a traditional web application. When the application starts, it examines the struct instances listed in the `Bind` field in the options, determines which methods are public (starts with an uppercase letter) and will generate JavaScript versions of those methods that can be called by the frontend code. + +:::info Note + +Wails requires that you pass in an _instance_ of the struct for it to bind it correctly + +::: + +In this example, we create a new `App` instance and then add this instance to the `Bind` option in `wails.Run`: + +```go {17,27} title="main.go" +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + + app := &App{} + + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + + +type App struct { + ctx context.Context +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +You may bind as many structs as you like. Just make sure you create an instance of it and pass it in `Bind`: + +```go {10-12} + //... + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + &mystruct1{}, + &mystruct2{}, + }, + }) + +``` + +When you run `wails dev` (or `wails generate module`), a frontend module will be generated containing the following: + +- JavaScript bindings for all bound methods +- TypeScript declarations for all bound methods +- TypeScript definitions for all Go structs used as inputs or outputs by the bound methods + +This makes it incredibly simple to call Go code from the frontend, using the same strongly typed datastructures. + +## The Frontend + +### Overview + +The frontend is a collection of files rendered by webkit. It's like a browser and webserver in one. There is virtually[^1] no limit to which frameworks or libraries you can use. The main points of interaction between the frontend and your Go code are: + +- Calling bound Go methods +- Calling runtime methods + +### Calling bound Go methods + +When you run your application with `wails dev`, it will automatically generate JavaScript bindings for your structs in a directory called `wailsjs/go` (You can also do this by running `wails generate module`). The generated files mirror the package names in your application. In the example above, we bind `app`, which has one public method `Greet`. This will lead to the generation of the following files: + +```bash +wailsjs + └─go + └─main + ├─App.d.ts + └─App.js +``` + +Here we can see that there is a `main` package that contains the JavaScript bindings for the bound `App` struct, as well as the TypeScript declaration file for those methods. To call `Greet` from our frontend, we simply import the method and call it like a regular JavaScript function: + +```javascript +// ... +import { Greet } from "../wailsjs/go/main/App"; + +function doGreeting(name) { + Greet(name).then((result) => { + // Do something with result + }); +} +``` + +The TypeScript declaration file gives you the correct types for the bound methods: + +```ts +export function Greet(arg1: string): Promise; +``` + +The generated methods return a Promise. A successful call will result in the first return value from the Go call to be passed to the `resolve` handler. An unsuccessful call is when a Go method that has an error type as it's second return value, passes an error instance back to the caller. This is passed back via the `reject` handler. In the example above, `Greet` only returns a `string` so the JavaScript call will never reject - unless invalid data is passed to it. + +All data types are correctly translated between Go and JavaScript. Even structs. If you return a struct from a Go call, it will be returned to your frontend as a JavaScript class. + +:::info Note + +Struct fields _must_ have a valid `json` tag to be included in the generated TypeScript. + +Anonymous nested structs are not supported at this time. + +::: + +It is possible to send structs back to Go. Any JavaScript map/class passed as an argument that is expecting a struct, will be converted to that struct type. To make this process a lot easier, in `dev` mode, a TypeScript module is generated, defining all the struct types used in bound methods. Using this module, it's possible to construct and send native JavaScript objects to the Go code. + +There is also support for Go methods that use structs in their signature. All Go structs specified by a bound method (either as parameters or return types) will have TypeScript versions auto generated as part of the Go code wrapper module. Using these, it's possible to share the same data model between Go and JavaScript. + +Example: We update our `Greet` method to accept a `Person` instead of a string: + +```go title="main.go" +type Person struct { + Name string `json:"name"` + Age uint8 `json:"age"` + Address *Address `json:"address"` +} + +type Address struct { + Street string `json:"street"` + Postcode string `json:"postcode"` +} + +func (a *App) Greet(p Person) string { + return fmt.Sprintf("Hello %s (Age: %d)!", p.Name, p.Age) +} +``` + +The `wailsjs/go/main/App.js` file will still have the following code: + +```js title="App.js" +export function Greet(arg1) { + return window["go"]["main"]["App"]["Greet"](arg1); +} +``` + +But the `wailsjs/go/main/App.d.ts` file will be updated with the following code: + +```ts title="App.d.ts" +import { main } from "../models"; + +export function Greet(arg1: main.Person): Promise; +``` + +As we can see, the "main" namespace is imported from a new "models.ts" file. This file contains all the struct definitions used by our bound methods. In this example, this is a `Person` struct. If we look at `models.ts`, we can see how the models are defined: + +```ts title="models.ts" +export namespace main { + export class Address { + street: string; + postcode: string; + + static createFrom(source: any = {}) { + return new Address(source); + } + + constructor(source: any = {}) { + if ("string" === typeof source) source = JSON.parse(source); + this.street = source["street"]; + this.postcode = source["postcode"]; + } + } + export class Person { + name: string; + age: number; + address?: Address; + + static createFrom(source: any = {}) { + return new Person(source); + } + + constructor(source: any = {}) { + if ("string" === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.age = source["age"]; + this.address = this.convertValues(source["address"], Address); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice) { + return (a as any[]).map((elem) => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } +} +``` + +So long as you have TypeScript as part of your frontend build configuration, you can use these models in the following way: + +```js title="mycode.js" +import { Greet } from "../wailsjs/go/main/App"; +import { main } from "../wailsjs/go/models"; + +function generate() { + let person = new main.Person(); + person.name = "Peter"; + person.age = 27; + Greet(person).then((result) => { + console.log(result); + }); +} +``` + +The combination of generated bindings and TypeScript models makes for a powerful development environment. + +More information on Binding can be found in the [Binding Methods](guides/application-development.mdx#binding-methods) section of the [Application Development Guide](guides/application-development.mdx). + +### Calling runtime methods + +The JavaScript runtime is located at `window.runtime` and contains many methods to do various tasks such as emit an event or perform logging operations: + +```js title="mycode.js" +window.runtime.EventsEmit("my-event", 1); +``` + +More details about the JS runtime can be found in the [Runtime Reference](reference/runtime/intro). + +[^1]: There is a very small subset of libraries that use features unsupported in WebViews. There are often alternatives and workarounds for such cases. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx new file mode 100644 index 00000000000..9afebec4d31 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx @@ -0,0 +1,75 @@ +--- +sidebar_position: 1 +--- + +# Введение + +Wails - это проект, позволяющий писать настольные приложения с использованием Go и web технологий. + +Считайте, что это легкая и быстрая альтернатива Electron для Go. Вы можете легко создавать приложения с гибкостью и мощностью Go, в сочетании с богатым современным фронтендом. + +### Возможности + +- Нативные меню, диалоги, темы и прозрачность +- Поддержка Windows, macOS и linux +- Встроенные шаблоны для Svelte, React, Preact, Vue, Lit и Vanilla JS +- Easily call Go methods from JavaScript +- Automatic Go struct to TypeScript model generation +- Для Windows не требуется CGO или внешние DLL +- Горячая перезагрузка, используя мощь [Vite](https://vitejs.dev/) +- Мощный CLI для простого создания, сборки и упаковки приложений +- Богатая [runtime библиотека](/docs/reference/runtime/intro) +- Приложения, созданные с помощью Wails совместимы с Apple и Microsoft Store + +Например, [varly](https://varly.app) - настольное приложение для MacOS и Windows, написанное с помощью Wails. Оно не только великолепно выглядит, но и использует системные меню и полупрозрачность - все, что можно ожидать от современного нативного приложения. + +```mdx-code-block +

+ + + +

+``` + +### Шаблоны для быстрого начала + +Wails поставляется с рядом предварительно настроенных шаблонов, которые позволяют вам быстро создать и запустить ваше приложение. Есть шаблоны для следующих фреймворков: Svelte, React, Vue, Preact, Lit и Vanilla. There are both JavaScript and TypeScript versions for each template. + +### Системные элементы + +Wails использует специально созданную библиотеку для обработки системных элементов, таких как окна, меню, диалоги и так далее, чтобы вы могли создавать хорошо выглядящие, богатые функционалом приложения. + +**It does not embed a browser**, so it delivers a small runtime. Instead, it reuses the native rendering engine for the platform. На Windows это новая библиотека Microsoft Webview2, основанная на Chromium. + +### Go & JavaScript Interoperability + +Wails automatically makes your Go methods available to JavaScript, so you can call them by name from your frontend! It even generates TypeScript models for the structs used by your Go methods, so you can pass the same data structures between Go and JavaScript. + +### Библиотека среды выполнения + +Wails provides a runtime library, for both Go and JavaScript, that handles a lot of the things modern applications need, like Eventing, Logging, Dialogs, etc. + +### Опыт разработки в реальном времени + +#### Автоматическая пересборка + +Когда вы запускаете ваше приложение в режиме разработки, Wails будет собирать его, но читать ресурсы с диска. Он будет отслеживать любые изменения в вашем коде на Go и автоматически пересобирать и перезапускать приложение. + +#### Автоматическая перезагрузка + +Когда будут обнаружены изменения ресурсов вашего приложения, ваше запущенное приложение перезагрузится, почти сразу, отражая ваши изменения. + +#### Разрабатывайте приложение в браузере + +Если вы предпочитаете отладку и разработку в браузере, то Wails это умеет. Запущенное приложение также имеет веб-сервер, который запустит ваше приложение в любом, подключенном к нему, браузере. Он будет перезапускаться когда ресурсы на вашем диске изменятся. + +### Бинарные файлы, готовые к выпуску + +Когда вы готовы сделать финальную сборку вашего приложения, CLI соберет всё в один исполняемый файл со всеми ресурсами внутри. На Windows и MacOS есть возможность создать нативный установочный пакет для распространения. Ресурсы, используемые при упаковке (иконка, info.plist, файл manifest'а, и т.д.) являются частью вашего проекта и могут быть изменены, что даёт вам полный контроль над тем, как вы создаете приложение. + +### Инструментарий + +Wails CLI предоставляет легкий способ генерировать, собирать и упаковывать ваши приложения. Оно создаст иконки, соберет ваше приложение с оптимальными параметрами и создаст готовый для распространения исполняемый файл. Выберите из нескольких стартовых шаблонов для быстрого старта! diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx new file mode 100644 index 00000000000..c7aea10a64d --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx @@ -0,0 +1,240 @@ +--- +sidebar_position: 2 +--- + +# CLI + +The Wails CLI has a number of commands that are used for managing your projects. All commands are run in the following way: + +`wails ` + +## init + +`wails init` is used for generating projects. + +| Flag | Description | Default | +|:------------------ |:----------------------------------------------------------------------------------------------------------------------- |:-------------------:| +| -n "project name" | Name of the project. **Mandatory**. | | +| -d "project dir" | Project directory to create | Name of the project | +| -g | Initialise git repository | | +| -l | List available project templates | | +| -q | Suppress output to console | | +| -t "template name" | The project template to use. This can be the name of a default template or a URL to a remote template hosted on github. | vanilla | +| -ide | Generate IDE project files | | +| -f | Force build application | false | + +Example: `wails init -n test -d mytestproject -g -ide vscode -q` + +This will generate a a project called "test" in the "mytestproject" directory, initialise git, generate vscode project files and do so silently. + +More information on using IDEs with Wails can be found [here](../guides/ides.mdx). + +### Remote Templates + +Remote templates (hosted on GitHub) are supported and can be installed by using the template's project URL. + +Example: `wails init -n test -t https://github.com/leaanthony/testtemplate[@v1.0.0]` + +A list of community maintained templates can be found [here](../community/templates.mdx) + +:::warning Attention + +**The Wails project does not maintain, is not responsible nor liable for 3rd party templates!** + +If you are unsure about a template, inspect `package.json` and `wails.json` for what scripts are run and what packages are installed. + +::: + +## build + +`wails build` is used for compiling your project to a production-ready binary. + +| Flag | Description | Default | +|:-------------------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |:--------------------------------------------------------------------------------------------------------------------------------------------------- | +| -clean | Cleans the `build/bin` directory | | +| -compiler "compiler" | Use a different go compiler to build, eg go1.15beta1 | go | +| -debug | Retains debug information in the application and shows the debug console. Allows the use of the devtools in the application window | | +| -devtools | Allows the use of the devtools in the application window in production (when -debug is not used). Ctrl/Cmd+Shift+F12 may be used to open the devtools window. *NOTE*: This option will make your application FAIL Mac appstore guidelines. Use for debugging only. | | +| -dryrun | Prints the build command without executing it | | +| -f | Force build application | | +| -garbleargs | Arguments to pass to garble | `-literals -tiny -seed=random` | +| -ldflags "flags" | Additional ldflags to pass to the compiler | | +| -m | Skip mod tidy before compile | | +| -nopackage | Do not package application | | +| -nocolour | Disable colour in output | | +| -nosyncgomod | Do not sync go.mod with the Wails version | | +| -nsis | Generate NSIS installer for Windows | | +| -o filename | Output filename | | +| -obfuscated | Obfuscate the application using [garble](https://github.com/burrowers/garble) | | +| -platform | Build for the given (comma delimited) [platforms](../reference/cli.mdx#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | platform = `GOOS` environment variable if given else `runtime.GOOS`.
arch = `GOARCH` envrionment variable if given else `runtime.GOARCH`. | +| -race | Build with Go's race detector | | +| -s | Skip building the frontend | | +| -skipbindings | Skip bindings generation | | +| -tags "extra tags" | Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated | | +| -trimpath | Remove all file system paths from the resulting executable. | | +| -u | Updates your project's `go.mod` to use the same version of Wails as the CLI | | +| -upx | Compress final binary using "upx" | | +| -upxflags | Flags to pass to upx | | +| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 | +| -webview2 | WebView2 installer strategy: download,embed,browser,error | download | +| -windowsconsole | Keep the console window for Windows builds | | + +For a detailed description of the `webview2` flag, please refer to the [Windows](../guides/windows.mdx) Guide. + +If you prefer to build using standard Go tooling, please consult the [Manual Builds](../guides/manual-builds.mdx) guide. + +Example: + +`wails build -clean -o myproject.exe` + +:::info + +On Mac, the application will be bundled with `Info.plist`, not `Info.dev.plist`. + +::: + +:::info UPX on Apple Silicon + +There are [issues](https://github.com/upx/upx/issues/446) with using UPX with Apple Silicon. + +::: + +:::info UPX on Windows + +Some Antivirus vendors false positively mark `upx` compressed binaries as virus, see [issue](https://github.com/upx/upx/issues/437). + +::: + +### Platforms + +Supported platforms are: + +| Platform | Description | +|:---------------- |:--------------------------------------------- | +| darwin | MacOS + architecture of build machine | +| darwin/amd64 | MacOS 10.13+ AMD64 | +| darwin/arm64 | MacOS 11.0+ ARM64 | +| darwin/universal | MacOS AMD64+ARM64 universal application | +| windows | Windows 10/11 + architecture of build machine | +| windows/amd64 | Windows 10/11 AMD64 | +| windows/arm64 | Windows 10/11 ARM64 | +| linux | Linux + architecture of build machine | +| linux/amd64 | Linux AMD64 | +| linux/arm64 | Linux ARM64 | + +## doctor + +`wails doctor` will run diagnostics to ensure that your system is ready for development. + +Example: + +``` +Wails CLI v2.0.0-beta + +Scanning system - Please wait (this may take a long time)...Done. + +System +------ +OS: Windows 10 Pro +Version: 2009 (Build: 19043) +ID: 21H1 +Go Version: go1.18 +Platform: windows +Architecture: amd64 + +Dependency Package Name Status Version +---------- ------------ ------ ------- +WebView2 N/A Installed 93.0.961.52 +npm N/A Installed 6.14.15 +*upx N/A Installed upx 3.96 + +* - Optional Dependency + +Diagnosis +--------- +Your system is ready for Wails development! + +``` + +## dev + +`wails dev` is used to run your application in a "live development" mode. This means: + +- The application's `go.mod` will be updated to use the same version of Wails as the CLI +- The application is compiled and run automatically +- A watcher is started and will trigger a rebuild of your dev app if it detects changes to your go files +- A webserver is started on `http://localhost:34115` which serves your application (not just frontend) over http. This allows you to use your favourite browser development extensions +- All application assets are loaded from disk. If they are changed, the application will automatically reload (not rebuild). All connected browsers will also reload +- A JS module is generated that provides the following: +- JavaScript wrappers of your Go methods with autogenerated JSDoc, providing code hinting +- TypeScript versions of your Go structs, that can be constructed and passed to your go methods +- A second JS module is generated that provides a wrapper + TS declaration for the runtime +- On macOS, it will bundle the application into a `.app` file and run it. It will use a `build/darwin/Info.dev.plist` for development. + +| Flag | Description | Default | +|:---------------------------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |:--------------------- | +| -appargs "args" | Arguments passed to the application in shell style | | +| -assetdir "./path/to/assets" | Serve assets from the given directory instead of using the provided asset FS | Value in `wails.json` | +| -browser | Opens a browser to `http://localhost:34115` on startup | | +| -compiler "compiler" | Use a different go compiler to build, eg go1.15beta1 | go | +| -debounce | The time to wait for reload after an asset change is detected | 100 (milliseconds) | +| -devserver "host:port" | The address to bind the wails dev server to | "localhost:34115" | +| -extensions | Extensions to trigger rebuilds (comma separated) | go | +| -forcebuild | Force build of application | | +| -frontenddevserverurl "url" | Use 3rd party dev server url to serve assets, EG Vite | "" | +| -ldflags "flags" | Additional ldflags to pass to the compiler | | +| -loglevel "loglevel" | Loglevel to use - Trace, Debug, Info, Warning, Error | Debug | +| -nocolour | Turn off colour cli output | false | +| -noreload | Disable automatic reload when assets change | | +| -nosyncgomod | Do not sync go.mod with the Wails version | false | +| -race | Build with Go's race detector | false | +| -reloaddirs | Additional directories to trigger reloads (comma separated) | Value in `wails.json` | +| -s | Skip building the frontend | false | +| -save | Saves the given `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce`, `devserver` and `frontenddevserverurl` flags in `wails.json` to become the defaults for subsequent invocations. | | +| -skipbindings | Skip bindings generation | | +| -tags "extra tags" | Build tags to pass to compiler (quoted and space separated) | | +| -v | Verbosity level (0 - silent, 1 - standard, 2 - verbose) | 1 | +| -wailsjsdir | The directory to generate the generated Wails JS modules | Value in `wails.json` | + +Example: + +`wails dev -assetdir ./frontend/dist -wailsjsdir ./frontend/src -browser` + +This command will do the following: + +- Build the application and run it (more details [here](../guides/manual-builds.mdx) +- Generate the Wails JS modules in `./frontend/src` +- Watch for updates to files in `./frontend/dist` and reload on any change +- Open a browser and connect to the application + +There is more information on using this feature with existing framework scripts [here](../guides/application-development.mdx#live-reloading). + +## generate + +### template + +Wails uses templates for project generation. The `wails generate template` command helps scaffold a template so that it may be used for generating projects. + +| Flag | Description | +|:---------------- |:------------------------------------------- | +| -name | The template name (Mandatory) | +| -frontend "path" | Path to frontend project to use in template | + +For more details on creating templates, consult the [Templates guide](../guides/templates.mdx). + +### module + +The `wails generate module` command allows you to manually generate the `wailsjs` directory for your application. + +## update + +`wails update` will update the version of the Wails CLI. + +| Flag | Description | +|:------------------ |:------------------------------------- | +| -pre | Update to latest pre-release version | +| -version "version" | Install a specific version of the CLI | + +## version + +`wails version` will simply output the current CLI version. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx new file mode 100644 index 00000000000..ff9a2442281 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx @@ -0,0 +1,230 @@ +--- +sidebar_position: 4 +--- + +# Menus + +It is possible to add an application menu to Wails projects. This is achieved by defining a [Menu](#menu) struct and setting it in the [`Menu`](../reference/options.mdx#menu) application config, or by calling the runtime method [MenuSetApplicationMenu](../reference/runtime/menu.mdx#menusetapplicationmenu). + +An example of how to create a menu: + +```go + + app := NewApp() + + AppMenu := menu.NewMenu() + FileMenu := AppMenu.AddSubmenu("File") + FileMenu.AddText("&Open", keys.CmdOrCtrl("o"), openFile) + FileMenu.AddSeparator() + FileMenu.AddText("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) { + runtime.Quit(app.ctx) + }) + + if runtime.GOOS == "darwin" { + AppMenu.Append(menu.EditMenu()) // on macos platform, we should append EditMenu to enable Cmd+C,Cmd+V,Cmd+Z... shortcut + } + + err := wails.Run(&options.App{ + Title: "Menus Demo", + Width: 800, + Height: 600, + Menu: AppMenu, // reference the menu above + Bind: []interface{}{ + app, + }, + ) + // ... +``` + +It is also possible to dynamically update the menu, by updating the menu struct and calling [MenuUpdateApplicationMenu](../reference/runtime/menu.mdx#menuupdateapplicationmenu). + +The example above uses helper methods, however it's possible to build the menu structs manually. + +## Menu + +A Menu is a collection of MenuItems: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +type Menu struct { + Items []*MenuItem +} +``` + +For the Application menu, each MenuItem represents a single menu such as "Edit". + +A simple helper method is provided for building menus: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func NewMenuFromItems(first *MenuItem, rest ...*MenuItem) *Menu +``` + +This makes the layout of the code more like that of a menu without the need to add the menu items manually after creating them. Alternatively, you can just create the menu items and add them to the menu manually. + +## MenuItem + +A MenuItem represents an item within a Menu. + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +// MenuItem represents a menu item contained in a menu +type MenuItem struct { + Label string + Role Role + Accelerator *keys.Accelerator + Type Type + Disabled bool + Hidden bool + Checked bool + SubMenu *Menu + Click Callback +} +``` + +| Field | Type | Notes | +| ----------- | ------------------------------------ | ------------------------------------------------------------- | +| Label | string | The menu text | +| Accelerator | [\*keys.Accelerator](#accelerator) | Key binding for this menu item | +| Type | [Type](#type) | Type of MenuItem | +| Disabled | bool | Disables the menu item | +| Hidden | bool | Hides this menu item | +| Checked | bool | Adds check to item (Checkbox & Radio types) | +| SubMenu | [\*Menu](#menu) | Sets the submenu | +| Click | [Callback](#callback) | Callback function when menu clicked | +| Role | string | Defines a [role](#role) for this menu item. Mac only for now. | + +### Accelerator + +Accelerators (sometimes called keyboard shortcuts) define a binding between a keystroke and a menu item. Wails defines an Accelerator as a combination or key + [Modifier](#modifier). They are available in the `"github.com/wailsapp/wails/v2/pkg/menu/keys"` package. + +Example: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines cmd+o on Mac and ctrl-o on Window/Linux + myShortcut := keys.CmdOrCtrl("o") +``` + +Keys are any single character on a keyboard with the exception of `+`, which is defined as `plus`. Some keys cannot be represented as characters so there are a set of named characters that may be used: + +| | | | | +|:-----------:|:-----:|:-----:|:---------:| +| `backspace` | `f1` | `f16` | `f31` | +| `tab` | `f2` | `f17` | `f32` | +| `return` | `f3` | `f18` | `f33` | +| `enter` | `f4` | `f19` | `f34` | +| `escape` | `f5` | `f20` | `f35` | +| `left` | `f6` | `f21` | `numlock` | +| `right` | `f7` | `f22` | | +| `up` | `f8` | `f23` | | +| `down` | `f9` | `f24` | | +| `space` | `f10` | `f25` | | +| `delete` | `f11` | `f36` | | +| `home` | `f12` | `f37` | | +| `end` | `f13` | `f38` | | +| `page up` | `f14` | `f39` | | +| `page down` | `f15` | `f30` | | + +Wails also supports parsing accelerators using the same syntax as Electron. This is useful for storing accelerators in config files. + +Example: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines cmd+o on Mac and ctrl-o on Window/Linux + myShortcut, err := keys.Parse("Ctrl+Option+A") +``` + +#### Modifier + +The following modifiers are keys that may be used in combination with the accelerator key: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" +const ( + // CmdOrCtrlKey represents Command on Mac and Control on other platforms + CmdOrCtrlKey Modifier = "cmdorctrl" + // OptionOrAltKey represents Option on Mac and Alt on other platforms + OptionOrAltKey Modifier = "optionoralt" + // ShiftKey represents the shift key on all systems + ShiftKey Modifier = "shift" + // ControlKey represents the control key on all systems + ControlKey Modifier = "ctrl" +) +``` + +A number of helper methods are available to create Accelerators using modifiers: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" +func CmdOrCtrl(key string) *Accelerator +func OptionOrAlt(key string) *Accelerator +func Shift(key string) *Accelerator +func Control(key string) *Accelerator +``` + +Modifiers can be combined using `keys.Combo(key string, modifier1 Modifier, modifier2 Modifier, rest ...Modifier)`: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines "Ctrl+Option+A" on Mac and "Ctrl+Alt+A" on Window/Linux + myShortcut := keys.Combo("a", ControlKey, OptionOrAltKey) +``` + +### Type + +Each menu item must have a type and there are 5 types available: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +const ( + TextType Type = "Text" + SeparatorType Type = "Separator" + SubmenuType Type = "Submenu" + CheckboxType Type = "Checkbox" + RadioType Type = "Radio" +) +``` + +For convenience, helper methods are provided to quickly create a menu item: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func Text(label string, accelerator *keys.Accelerator, click Callback) *MenuItem +func Separator() *MenuItem +func Radio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func Checkbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func SubMenu(label string, menu *Menu) *Menu +``` + +You can also create menu items directly on a menu by using the "Add" helpers: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func (m *Menu) AddText(label string, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddSeparator() *MenuItem +func (m *Menu) AddRadio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddCheckbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddSubMenu(label string, menu *Menu) *MenuI +``` + +A note on radio groups: A radio group is defined as a number of radio menu items that are next to each other in the menu. This means that you do not need to group items together as it is automatic. However, that also means you cannot have 2 radio groups next to each other - there must be a non-radio item between them. + +### Callback + +Each menu item may have a callback that is executed when the item is clicked: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +type Callback func(*CallbackData) + +type CallbackData struct { + MenuItem *MenuItem +} +``` + +The function is given a `CallbackData` struct which indicates which menu item triggered the callback. This is useful when using radio groups that may share a callback. + +### Role + +:::info Roles + +Roles are currently supported on Mac only. + +::: + +A menu item may have a role, which is essentially a pre-defined menu item. We currently support the following roles: + +| Role | Description | +| ------------ | ------------------------------------------------------------------------ | +| AppMenuRole | The standard Mac application menu. Can be created using `menu.AppMenu()` | +| EditMenuRole | The standard Mac edit menu. Can be created using `menu.EditMenu()` | diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx new file mode 100644 index 00000000000..46d1c071b60 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx @@ -0,0 +1,853 @@ +--- +sidebar_position: 3 +--- + +# Options + +## Application Options + +The `Options.App` struct contains the application configuration. It is passed to the `wails.Run()` method: + +```go title="Example" +import ( + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/linux" + "github.com/wailsapp/wails/v2/pkg/options/mac" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +func main() { + + err := wails.Run(&options.App{ + Title: "Menus Demo", + Width: 800, + Height: 600, + DisableResize: false, + Fullscreen: false, + WindowStartState: options.Maximised, + Frameless: true, + MinWidth: 400, + MinHeight: 400, + MaxWidth: 1280, + MaxHeight: 1024, + StartHidden: false, + HideWindowOnClose: false, + BackgroundColour: &options.RGBA{R: 0, G: 0, B: 0, A: 255}, + AlwaysOnTop: false, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: assetsHandler, + Middleware: assetsMidldeware, + }, + Menu: app.applicationMenu(), + Logger: nil, + LogLevel: logger.DEBUG, + LogLevelProduction: logger.ERROR, + OnStartup: app.startup, + OnDomReady: app.domready, + OnShutdown: app.shutdown, + OnBeforeClose: app.beforeClose, + CSSDragProperty: "--wails-draggable", + CSSDragValue: "drag", + EnableDefaultContextMenu: false, + EnableFraudulentWebsiteDetection: false, + ZoomFactor: 1.0, + IsZoomControlEnabled: false, + Bind: []interface{}{ + app, + }, + ErrorFormatter: func(err error) any { return err.Error() }, + Windows: &windows.Options{ + WebviewIsTransparent: false, + WindowIsTranslucent: false, + BackdropType: windows.Mica, + DisableWindowIcon: false, + DisableFramelessWindowDecorations: false, + WebviewUserDataPath: "", + WebviewBrowserPath: "", + Theme: windows.SystemDefault, + CustomTheme: &windows.ThemeSettings{ + DarkModeTitleBar: windows.RGB(20, 20, 20), + DarkModeTitleText: windows.RGB(200, 200, 200), + DarkModeBorder: windows.RGB(20, 0, 20), + LightModeTitleBar: windows.RGB(200, 200, 200), + LightModeTitleText: windows.RGB(20, 20, 20), + LightModeBorder: windows.RGB(200, 200, 200), + }, + // User messages that can be customised + Messages *windows.Messages + // OnSuspend is called when Windows enters low power mode + OnSuspend func() + // OnResume is called when Windows resumes from low power mode + OnResume func(), + WebviewGpuDisabled: false, + }, + Mac: &mac.Options{ + TitleBar: &mac.TitleBar{ + TitlebarAppearsTransparent: true, + HideTitle: false, + HideTitleBar: false, + FullSizeContent: false, + UseToolbar: false, + HideToolbarSeparator: true, + }, + Appearance: mac.NSAppearanceNameDarkAqua, + WebviewIsTransparent: true, + WindowIsTranslucent: false, + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + Linux: &linux.Options{ + Icon: icon, + WindowIsTranslucent: false, + WebviewGpuPolicy: linux.WebviewGpuPolicyAlways, + ProgramName: "wails" + }, + Debug: options.Debug{ + OpenInspectorOnStartup: false, + }, + }) + + if err != nil { + log.Fatal(err) + } +} + +``` + +### Title + +The text shown in the window's title bar. + +Name: Title
Type: `string` + +### Width + +The initial width of the window. + +Name: Width
Type: `int`
Default: 1024. + +### Height + +The initial height of the window. + +Name: Height
Type: `int`
Default: 768 + +### DisableResize + +By default, the main window is resizable. Setting this to `true` will keep it a fixed size. + +Name: DisableResize
Type: `bool` + +### Fullscreen + +Deprecated: Please use [WindowStartState](#windowstartstate). + +### WindowStartState + +Defines how the window should present itself at startup. + +| Value | Win | Mac | Lin | +| ---------- | --- | --- | --- | +| Fullscreen | ✅ | ✅ | ✅ | +| Maximised | ✅ | ✅ | ✅ | +| Minimised | ✅ | ❌ | ✅ | + +Name: WindowStartState
Type: `options.WindowStartState` + +### Frameless + +When set to `true`, the window will have no borders or title bar. Also see [Frameless Windows](../guides/frameless.mdx). + +Name: Frameless
Type: `bool` + +### MinWidth + +This sets the minimum width for the window. If the value given in `Width` is less than this value, the window will be set to `MinWidth` by default. + +Name: MinWidth
Type: `int` + +### MinHeight + +This sets the minimum height for the window. If the value given in `Height` is less than this value, the window will be set to `MinHeight` by default. + +Name: MinHeight
Type: `int` + +### MaxWidth + +This sets the maximum width for the window. If the value given in `Width` is more than this value, the window will be set to `MaxWidth` by default. + +Name: MaxWidth
Type: `int` + +### MaxHeight + +This sets the maximum height for the window. If the value given in `Height` is more than this value, the window will be set to `MaxHeight` by default. + +Name: MaxHeight
Type: `int` + +### StartHidden + +When set to `true`, the application will be hidden until [WindowShow](../reference/runtime/window.mdx#windowshow) is called. + +Name: StartHidden
Type: `bool` + +### HideWindowOnClose + +By default, closing the window will close the application. Setting this to `true` means closing the window will + +hide the window instead. + +Name: HideWindowOnClose
Type: `bool` + +### BackgroundColour + +This value is the default background colour of the window. Example: options.NewRGBA(255,0,0,128) - Red at 50% transparency + +Name: BackgroundColour
Type: `*options.RGBA`
Default: white + +### AlwaysOnTop + +Indicates that the window should stay above other windows when losing focus. + +Name: AlwaysOnTop
Type: `bool` + +### Assets + +Deprecated: Please use Assets on [AssetServer specific options](#assetserver). + +### AssetsHandler + +Deprecated: Please use AssetsHandler on [AssetServer specific options](#assetserver). + +### AssetServer + +This defines AssetServer specific options. It allows to customize the AssetServer with static assets, serving assets dynamically with an `http.Handler` or hook into the request chain with an `assetserver.Middleware`. + +Not all features of an `http.Request` are currently supported, please see the following feature matrix: + +| Feature | Win | Mac | Lin | +| ----------------------- | --- | --- | ------ | +| GET | ✅ | ✅ | ✅ | +| POST | ✅ | ✅ | ✅ [^1] | +| PUT | ✅ | ✅ | ✅ [^1] | +| PATCH | ✅ | ✅ | ✅ [^1] | +| DELETE | ✅ | ✅ | ✅ [^1] | +| Request Headers | ✅ | ✅ | ✅ [^1] | +| Request Body | ✅ | ✅ | ✅ [^2] | +| Request Body Streaming | ✅ | ✅ | ✅ [^2] | +| Response StatusCodes | ✅ | ✅ | ✅ [^1] | +| Response Headers | ✅ | ✅ | ✅ [^1] | +| Response Body | ✅ | ✅ | ✅ | +| Response Body Streaming | ❌ | ✅ | ✅ | +| WebSockets | ❌ | ❌ | ❌ | +| HTTP Redirects 30x | ✅ | ❌ | ❌ | + +Name: AssetServer
Type: `*assetserver.Options` + +#### Assets + +The static frontend assets to be used by the application. + +A GET request is first tried to be served from this `fs.FS`. If the `fs.FS` returns `os.ErrNotExist` for that file, the request handling will fallback to the [Handler](#handler) and tries to serve the GET request from it. + +If set to nil, all GET requests will be forwarded to [Handler](#handler). + +Name: Assets
Type: `fs.FS` + +#### Handler + +The assets handler is a generic `http.Handler` for fallback handling of assets that can't be found. + +The handler will be called for every GET request that can't be served from [Assets](#assets), due to `os.ErrNotExist`. Furthermore all non GET requests will always be served from this Handler. If not defined, the result is the following in cases where the Handler would have been called: + +- GET request: `http.StatusNotFound` +- Other request: `http.StatusMethodNotAllowed` + +NOTE: When used in combination with a Frontend DevServer there might be limitations, eg. Vite serves the index.html on every path, that does not contain a file extension. + +Name: AssetsHandler
Type: `http.Handler` + +#### Middleware + +Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default request handler dynamically, e.g. implement specialized Routing etc. The Middleware is called to build a new `http.Handler` used by the AssetSever and it also receives the default handler used by the AssetServer as an argument. + +If not defined, the default AssetServer request chain is executed. + +Name: Middleware
Type: `assetserver.Middleware` + +### Menu + +The menu to be used by the application. More details about Menus in the [Menu Reference](../reference/runtime/menu.mdx). + +:::note + +On Mac, if no menu is specified, a default menu will be created. + +::: + +Name: Menu
Type: `*menu.Menu` + +### Logger + +The logger to be used by the application. More details about logging in the [Log Reference](../reference/runtime/log.mdx). + +Name: Logger
Type: `logger.Logger`
Default: Logs to Stdout + +### LogLevel + +The default log level. More details about logging in the [Log Reference](../reference/runtime/log.mdx). + +Name: LogLevel
Type: `logger.LogLevel`
Default: `Info` in dev mode, `Error` in production mode + +### LogLevelProduction + +The default log level for production builds. More details about logging in the [Log Reference](../reference/runtime/log.mdx). + +Name: LogLevelProduction
Type: `logger.LogLevel`
Default: `Error` + +### OnStartup + +This callback is called after the frontend has been created, but before `index.html` has been loaded. It is given the application context. + +Name: OnStartup
Type: `func(ctx context.Context)` + +### OnDomReady + +This callback is called after the frontend has loaded `index.html` and its resources. It is given the application context. + +Name: OnDomReady
Type: `func(ctx context.Context)` + +### OnShutdown + +This callback is called after the frontend has been destroyed, just before the application terminates. It is given the application context. + +Name: OnShutdown
Type: `func(ctx context.Context)` + +### OnBeforeClose + +If this callback is set, it will be called when the application is about to quit, either by clicking the window close button or calling `runtime.Quit`. Returning true will cause the application to continue, false will continue shutdown as normal. This is good for confirming with the user that they wish to exit the program. + +Example: + +```go title=windowsapp.go +func (b *App) beforeClose(ctx context.Context) (prevent bool) { + dialog, err := runtime.MessageDialog(ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Quit?", + Message: "Are you sure you want to quit?", + }) + + if err != nil { + return false + } + return dialog != "Yes" +} +``` + +Name: OnBeforeClose
Type: `func(ctx context.Context) bool` + +### CSSDragProperty + +Indicates the CSS property to use to identify which elements can be used to drag the window. Default: `--wails-draggable`. + +Name: CSSDragProperty
Type: `string` + +### CSSDragValue + +Indicates what value the `CSSDragProperty` style should have to drag the window. Default: `drag`. + +Name: CSSDragValue
Type: `string` + +### EnableDefaultContextMenu + +EnableDefaultContextMenu enables the browser's default context-menu in production. + +By default, the browser's default context-menu is only available in development and in a `-debug` [build](../reference/cli.mdx#build) along with the devtools inspector, Using this option you can enable the default context-menu in `production` while the devtools inspector won't be available unless the `-devtools` build flag is used. + +When this option is enabled, by default the context-menu will only be shown for text contexts (where Cut/Copy/Paste is needed), to override this behavior, you can use the CSS property `--default-contextmenu` on any HTML element (including the `body`) with the following values : + +| CSS Style | Behavior | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--default-contextmenu: auto;` | (**default**) will show the default context menu only if :
contentEditable is true OR text has been selected OR element is input or textarea | +| `--default-contextmenu: show;` | will always show the default context menu | +| `--default-contextmenu: hide;` | will always hide the default context menu | + +This rule is inherited like any normal CSS rule, so nesting works as expected. + +:::note +This filtering functionality is only enabled in production, so in development and in debug build, the full context-menu is always available everywhere. +::: + +:::warning +This filtering functionality is NOT a security measure, the developer should expect that the full context-menu could be leaked anytime which could contain commands like (Download image, Reload, Save webpage), if this is a concern, the developer SHOULD NOT enable the default context-menu. +::: + + +Name: EnableDefaultContextMenu
Type: `bool` + +### EnableFraudulentWebsiteDetection + +EnableFraudulentWebsiteDetection enables scan services for fraudulent content, such as malware or phishing attempts. These services might send information from your app like URLs navigated to and possibly other content to cloud services of Apple and Microsoft. + +Name: EnableFraudulentWebsiteDetection
Type: `bool` + +### ZoomFactor + +Name: ZoomFactor
Type: `float64` + +This defines the zoom factor for the WebView2. This is the option matching the Edge user activated zoom in or out. + +### IsZoomControlEnabled + +Name: IsZoomControlEnabled
Type: `bool` + +This enables the zoom factor to be changed by the user. Please note that the zoom factor can be set in the options while disallowing the user to change it at runtime (f.e. for a kiosk application or similar). + +### Bind + +A slice of struct instances defining methods that need to be bound to the frontend. + +Name: Bind
Type: `[]interface{}` + +### ErrorFormatter + +A function that determines how errors are formatted when returned by a JS-to-Go method call. The returned value will be marshalled as JSON. + +Name: ErrorFormatter
Type: `func (error) any` + +### Windows + +This defines [Windows specific options](#windows). + +Name: Windows
Type: `*windows.Options` + +#### WebviewIsTransparent + +Setting this to `true` will make the webview background transparent when an alpha value of `0` is used. This means that if you use `rgba(0,0,0,0)` for `background-color` in your CSS, the host window will show through. Often combined with [WindowIsTranslucent](#WindowIsTranslucent) to make frosty-looking applications. + +Name: WebviewIsTransparent
Type: `bool` + +#### WindowIsTranslucent + +Setting this to `true` will make the window background translucent. Often combined with [WebviewIsTransparent](#WebviewIsTransparent). + +For Windows 11 versions before build 22621, this will use the [BlurBehind](https://learn.microsoft.com/en-us/windows/win32/dwm/blur-ovw) method for translucency, which can be slow. For Windows 11 versions after build 22621, this will enable the newer translucency types that are much faster. By default, the type of translucency used will be determined by Windows. To configure this, use the [BackdropType](#BackdropType) option. + +Name: WindowIsTranslucent
Type: `bool` + +#### BackdropType + +:::note + +Requires Windows 11 build 22621 or later. + +::: + +Sets the translucency type of the window. This is only applicable if [WindowIsTranslucent](#WindowIsTranslucent) is set to `true`. + +Name: BackdropType
Type `windows.BackdropType` + +The value can be one of the following: + +| Value | Description | +| ------- | ----------------------------------------------------------------------------------------- | +| Auto | Let Windows decide which backdrop to use | +| None | Do not use translucency | +| Acrylic | Use [Acrylic](https://learn.microsoft.com/en-us/windows/apps/design/style/acrylic) effect | +| Mica | Use [Mica](https://learn.microsoft.com/en-us/windows/apps/design/style/mica) effect | +| Tabbed | Use Tabbed. This is a backdrop that is similar to Mica. | + +#### DisableWindowIcon + +Setting this to `true` will remove the icon in the top left corner of the title bar. + +Name: DisableWindowIcon
Type: `bool` + +#### DisableFramelessWindowDecorations + +Setting this to `true` will remove the window decorations in [Frameless](#Frameless) mode. This means there will be no 'Aero Shadow' and no 'Rounded Corners' shown for the window. Please note that 'Rounded Corners' are only supported on Windows 11. + +Name: DisableFramelessWindowDecorations
Type: `bool` + +#### WebviewUserDataPath + +This defines the path where the WebView2 stores the user data. If empty `%APPDATA%\[BinaryName.exe]` will be used. + +Name: WebviewUserDataPath
Type: `string` + +#### WebviewBrowserPath + +This defines the path to a directory with WebView2 executable files and libraries. If empty, webview2 installed in the system will be used. + +Important information about distribution of fixed version runtime: + +- [How to get and extract runtime](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#details-about-the-fixed-version-runtime-distribution-mode) +- [Known issues for fixed version](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#known-issues-for-fixed-version) +- [The path of fixed version of the WebView2 Runtime should not contain \Edge\Application\.](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.1245.22#createcorewebview2environmentwithoptions) + +Name: WebviewBrowserPath
Type: `string` + +#### Theme + +Minimum Windows Version: Windows 10 2004/20H1 + +This defines the theme that the application should use: + +| Value | Description | +| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| SystemDefault | _Default_. The theme will be based on the system default. If the user changes their theme, the application will update to use the new setting | +| Dark | The application will use a dark theme exclusively | +| Light | The application will use a light theme exclusively | + +Name: Theme
Type: `windows.Theme` + +#### CustomTheme + +:::note + +Minimum Windows Version: Windows 10/11 2009/21H2 Build 22000 + +::: + +Allows you to specify custom colours for TitleBar, TitleText and Border for both light and dark mode, as well as when the window is active or inactive. + +Name: CustomTheme
Type: `windows.CustomTheme` + +##### CustomTheme type + +The CustomTheme struct uses `int32` to specify the colour values. These are in the standard(!) Windows format of: `0x00BBGGAA`. A helper function is provided to do RGB conversions into this format: `windows.RGB(r,g,b uint8)`. + +NOTE: Any value not provided will default to black. + +```go +type ThemeSettings struct { + DarkModeTitleBar int32 + DarkModeTitleBarInactive int32 + DarkModeTitleText int32 + DarkModeTitleTextInactive int32 + DarkModeBorder int32 + DarkModeBorderInactive int32 + LightModeTitleBar int32 + LightModeTitleBarInactive int32 + LightModeTitleText int32 + LightModeTitleTextInactive int32 + LightModeBorder int32 + LightModeBorderInactive int32 +} +``` + +Example: + +```go + CustomTheme: &windows.ThemeSettings{ + // Theme to use when window is active + DarkModeTitleBar: windows.RGB(255, 0, 0), // Red + DarkModeTitleText: windows.RGB(0, 255, 0), // Green + DarkModeBorder: windows.RGB(0, 0, 255), // Blue + LightModeTitleBar: windows.RGB(200, 200, 200), + LightModeTitleText: windows.RGB(20, 20, 20), + LightModeBorder: windows.RGB(200, 200, 200), + // Theme to use when window is inactive + DarkModeTitleBarInactive: windows.RGB(128, 0, 0), + DarkModeTitleTextInactive: windows.RGB(0, 128, 0), + DarkModeBorderInactive: windows.RGB(0, 0, 128), + LightModeTitleBarInactive: windows.RGB(100, 100, 100), + LightModeTitleTextInactive: windows.RGB(10, 10, 10), + LightModeBorderInactive: windows.RGB(100, 100, 100), + }, +``` + +#### Messages + +A struct of strings used by the webview2 installer if a valid webview2 runtime is not found. + +Name: Messages
Type: `*windows.Messages` + +Customise this for any language you choose to support. + +#### ResizeDebounceMS + +ResizeDebounceMS is the amount of time to debounce redraws of webview2 when resizing the window. The default value (0) will perform redraws as fast as it can. + +Name: ResizeDebounceMS
Type: `uint16` + +#### OnSuspend + +If set, this function will be called when Windows initiates a switch to low power mode (suspend/hibernate) + +Name: OnSuspend
Type: `func()` + +#### OnResume + +If set, this function will be called when Windows resumes from low power mode (suspend/hibernate) + +Name: OnResume
Type: `func()` + +#### WebviewGpuIsDisabled + +Setting this to `true` will disable GPU hardware acceleration for the webview. + +Name: WebviewGpuIsDisabled
Type: `bool` + +#### EnableSwipeGestures + +Setting this to `true` will enable swipe gestures for the webview. + +Name: EnableSwipeGestures
Type: `bool` + +### Mac + +This defines [Mac specific options](#mac). + +Name: Mac
Type: `*mac.Options` + +#### TitleBar + +The TitleBar struct provides the ability to configure the look and feel of the title bar. + +Name: TitleBar
Type: [`*mac.TitleBar`](#titlebar-struct) + +##### Titlebar struct + +The titlebar of the application can be customised by using the TitleBar options: + +```go +type TitleBar struct { + TitlebarAppearsTransparent bool + HideTitle bool + HideTitleBar bool + FullSizeContent bool + UseToolbar bool + HideToolbarSeparator bool +} +``` + +| Name | Description | +| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| TitlebarAppearsTransparent | Makes the titlebar transparent. This has the effect of hiding the titlebar and the content fill the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindow/1419167-titlebarappearstransparent?language=objc) | +| HideTitle | Hides the title of the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindowtitlevisibility?language=objc) | +| HideTitleBar | Removes [NSWindowStyleMaskTitled](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemasktitled/) from the style mask | +| FullSizeContent | Makes the webview fill the entire window. [Apple Docs](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemaskfullsizecontentview) | +| UseToolbar | Adds a default toolbar to the window. [Apple Docs](https://developer.apple.com/documentation/appkit/nstoolbar?language=objc) | +| HideToolbarSeparator | Removes the line beneath the toolbar. [Apple Docs](https://developer.apple.com/documentation/appkit/nstoolbar/1516954-showsbaselineseparator?language=objc) | + +Preconfigured titlebar settings are available: + +| Setting | Example | +| --------------------------- | ---------------------------------------------- | +| `mac.TitleBarDefault()` | ![](/img/reference/titlebar-default.webp) | +| `mac.TitleBarHidden()` | ![](/img/reference/titlebar-hidden.webp) | +| `mac.TitleBarHiddenInset()` | ![](/img/reference/titlebar-hidden-inset.webp) | + +Example: + +```go +Mac: &mac.Options{ + TitleBar: mac.TitleBarHiddenInset(), +} +``` + +Click [here](https://github.com/lukakerr/NSWindowStyles) for some inspiration on customising the titlebar. + +#### Appearance + +Appearance is used to set the style of your app in accordance with Apple's [NSAppearance](https://developer.apple.com/documentation/appkit/nsappearancename?language=objc) names. + +Name: Appearance
Type: [`mac.AppearanceType`](#appearance-type) + +##### Appearance type + +You can specify the application's [appearance](https://developer.apple.com/documentation/appkit/nsappearance?language=objc). + +| Value | Description | +| ----------------------------------------------------- | --------------------------------------------------------------- | +| DefaultAppearance | DefaultAppearance uses the default system value | +| NSAppearanceNameAqua | The standard light system appearance | +| NSAppearanceNameDarkAqua | The standard dark system appearance | +| NSAppearanceNameVibrantLight | The light vibrant appearance | +| NSAppearanceNameAccessibilityHighContrastAqua | A high-contrast version of the standard light system appearance | +| NSAppearanceNameAccessibilityHighContrastDarkAqua | A high-contrast version of the standard dark system appearance | +| NSAppearanceNameAccessibilityHighContrastVibrantLight | A high-contrast version of the light vibrant appearance | +| NSAppearanceNameAccessibilityHighContrastVibrantDark | A high-contrast version of the dark vibrant appearance | + +Example: + +```go +Mac: &mac.Options{ + Appearance: mac.NSAppearanceNameDarkAqua, +} +``` + +#### WebviewIsTransparent + +Setting this to `true` will make the webview background transparent when an alpha value of `0` is used. This means that if you use `rgba(0,0,0,0)` for `background-color` in your CSS, the host window will show through. Often combined with [WindowIsTranslucent](#WindowIsTranslucent) to make frosty-looking applications. + +Name: WebviewIsTransparent
Type: `bool` + +#### WindowIsTranslucent + +Setting this to `true` will make the window background translucent. Often combined with [WebviewIsTransparent](#WebviewIsTransparent) to make frosty-looking applications. + +Name: WindowIsTranslucent
Type: `bool` + +#### Preferences + +The Preferences struct provides the ability to configure the Webview preferences. + +Name: Preferences
Type: [`*mac.Preferences`](#preferences-struct) + +##### Preferences struct + +You can specify the webview preferences. + +```go +type Preferences struct { + TabFocusesLinks u.Bool + TextInteractionEnabled u.Bool + FullscreenEnabled u.Bool +} +``` + +| Name | Description | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| TabFocusesLinks | A Boolean value that indicates whether pressing the tab key changes the focus to links and form controls. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/2818595-tabfocuseslinks?language=objc) | +| TextInteractionEnabled | A Boolean value that indicates whether to allow people to select or otherwise interact with text. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3727362-textinteractionenabled?language=objc) | +| FullscreenEnabled | A Boolean value that indicates whether a web view can display content full screen. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3917769-elementfullscreenenabled?language=objc) | + +Example: + +```go +Mac: &mac.Options{ + Preferences: &mac.Preferences{ + TabFocusesLinks: mac.Enabled, + TextInteractionEnabled: mac.Disabled, + FullscreenEnabled: mac.Enabled, + } +} +``` + +#### About + +This configuration lets you set the title, message and icon for the "About" menu item in the app menu created by the "AppMenu" role. + +Name: About
Type: [`*mac.AboutInfo`](#about-struct) + +##### About struct + +```go + +type AboutInfo struct { + Title string + Message string + Icon []byte +} +``` + +If these settings are provided, an "About" menu item will appear in the app menu (when using the `AppMenu` role). Given this configuration: + +```go +//go:embed build/appicon.png +var icon []byte + +func main() { + err := wails.Run(&options.App{ + ... + Mac: &mac.Options{ + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + }) +``` + +The "About" menu item will appear in the app menu: + +```mdx-code-block +
+ +
+
+``` + +When clicked, that will open an about message box: + +```mdx-code-block +
+ +
+
+``` + +### Linux + +This defines [Linux specific options](#linux). + +Name: Linux
Type: `*linux.Options` + +#### Icon + +Sets up the icon representing the window. This icon is used when the window is minimized (also known as iconified). + +Name: Icon
Type: `[]byte` + +Some window managers or desktop environments may also place it in the window frame, or display it in other contexts. On others, the icon is not used at all, so your mileage may vary. + +NOTE: Gnome on Wayland at least does not display this icon. To have a application icon there, a `.desktop` file has to be used. On KDE it should work. + +The icon should be provided in whatever size it was naturally drawn; that is, don’t scale the image before passing it. Scaling is postponed until the last minute, when the desired final size is known, to allow best quality. + +#### WindowIsTranslucent + +Setting this to `true` will make the window background translucent. Some window managers may ignore it, or result in a black window. + +Name: WindowIsTranslucent
Type: `bool` + +#### WebviewGpuPolicy + +This option is used for determining the webview's hardware acceleration policy. + +Name: WebviewGpuPolicy
Type: [`options.WebviewGpuPolicy`](#webviewgpupolicy-type)
Default: `WebviewGpuPolicyAlways` + +##### WebviewGpuPolicy type + +| Value | Description | +| ------------------------ | -------------------------------------------------------------------- | +| WebviewGpuPolicyAlways | Hardware acceleration is always enabled | +| WebviewGpuPolicyOnDemand | Hardware acceleration is enabled/disabled as request by web contents | +| WebviewGpuPolicyNever | Hardware acceleration is always disabled | + +#### ProgramName + +This option is used to set the program's name for the window manager via GTK's g_set_prgname(). This name should not be localized, [see the docs](https://docs.gtk.org/glib/func.set_prgname.html). + +When a .desktop file is created this value helps with window grouping and desktop icons when the .desktop file's `Name` property differs form the executable's filename. + +Name: ProgramName
Type: string
+ +### Debug + +This defines [Debug specific options](#Debug) that apply to debug builds. + +Name: Debug
Type: `options.Debug` + +#### OpenInspectorOnStartup + +Setting this to `true` will open the WebInspector on startup of the application. + +Name: OpenInspectorOnStartup
Type: `bool` + +[^1]: This requires WebKit2GTK 2.36+ support and your app needs to be build with the build tag `webkit2_36` to activate support for this feature. This also bumps the minimum requirement of WebKit2GTK to 2.36 for your app. +[^2]: This requires WebKit2GTK 2.40+ support and your app needs to be build with the build tag `webkit2_40` to activate support for this feature. This also bumps the minimum requirement of WebKit2GTK to 2.40 for your app. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx new file mode 100644 index 00000000000..8e763502bcc --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx @@ -0,0 +1,92 @@ +--- +sidebar_position: 5 +--- + +# Project Config + +The project config resides in the `wails.json` file in the project directory. The structure of the config is: + +```json5 +{ + // Project config version + "version": "", + // The project name + "name": "", + // Relative path to the directory containing the compiled assets, this is normally inferred and could be left empty + "assetdir": "", + // Additional directories to trigger reloads (comma separated), this is only used for some advanced asset configurations + "reloaddirs": "", + // The directory where the build files reside. Defaults to 'build' + "build:dir": "", + // Relative path to the frontend directory. Defaults to 'frontend' + "frontend:dir": "", + // The command to install node dependencies, run in the frontend directory - often `npm install` + "frontend:install": "", + // The command to build the assets, run in the frontend directory - often `npm run build` + "frontend:build": "", + // This command has been replaced by frontend:dev:build. If frontend:dev:build is not specified will falls back to this command. \nIf this command is also not specified will falls back to frontend:build + "frontend:dev": "", + // This command is the dev equivalent of frontend:build. If not specified falls back to frontend:dev + "frontend:dev:build": "", + // This command is the dev equivalent of frontend:install. If not specified falls back to frontend:install + "frontend:dev:install": "", + // This command is run in a separate process on `wails dev`. Useful for 3rd party watchers or starting 3d party dev servers + "frontend:dev:watcher": "", + // URL to a 3rd party dev server to be used to serve assets, EG Vite. \nIf this is set to 'auto' then the devServerUrl will be inferred from the Vite output + "frontend:dev:serverUrl": "", + // Relative path to the directory that the auto-generated JS modules will be created + "wailsjsdir": "", + // The name of the binary + "outputfilename": "", + // The default time the dev server waits to reload when it detects a change in assets + "debounceMS": 100, + // Address to bind the wails dev sever to. Default: localhost:34115 + "devServer": "", + // Arguments passed to the application in shell style when in dev mode + "appargs": "", + // Defines if build hooks should be run though they are defined for an OS other than the host OS. + "runNonNativeBuildHooks": false, + "preBuildHooks": { + // The command that will be executed before a build of the specified GOOS/GOARCH: ${platform} is replaced with the "GOOS/GOARCH". The "GOOS/GOARCH" hook is executed before the "GOOS/*" and "*/*" hook. + "GOOS/GOARCH": "", + // The command that will be executed before a build of the specified GOOS: ${platform} is replaced with the "GOOS/GOARCH". The "GOOS/*" hook is executed before the "*/*" hook. + "GOOS/*": "", + // The command that will be executed before every build: ${platform} is replaced with the "GOOS/GOARCH". + "*/*": "" + }, + "postBuildHooks": { + // The command that will be executed after a build of the specified GOOS/GOARCH: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. The "GOOS/GOARCH" hook is executed before the "GOOS/*" and "*/*" hook. + "GOOS/GOARCH": "", + // The command that will be executed after a build of the specified GOOS: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. The "GOOS/*" hook is executed before the "*/*" hook. + "GOOS/*": "", + // The command that will be executed after every build: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. + "*/*": "" + }, + // Data used to populate manifests and version info. + "info": { + // The company name. Default: [The project name] + "companyName": "", + // The product name. Default: [The project name] + "productName": "", + // The version of the product. Default: '1.0.0' + "productVersion": "", + // The copyright of the product. Default: 'Copyright.........' + "copyright": "", + // A short comment of the app. Default: 'Built using Wails (https://wails.app)' + "comments": "" + }, + // 'multiple': One installer per architecture. 'single': Single universal installer for all architectures being built. Default: 'multiple' + "nsisType": "", + // Whether the app should be obfuscated. Default: false + "obfuscated": "", + // The arguments to pass to the garble command when using the obfuscated flag + "garbleargs": "" +} +``` + +This file is read by the Wails CLI when running `wails build` or `wails dev`. + +The `assetdir`, `reloaddirs`, `wailsjsdir`, `debounceMS`, `devserver` and `frontenddevserverurl` flags in `wails build/dev` will update the project config +and thus become defaults for subsequent runs. + +The JSON Schema for this file is located [here](https://wails.io/schemas/config.v2.json). diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx new file mode 100644 index 00000000000..f45c13c46a6 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx @@ -0,0 +1,13 @@ +--- +sidebar_position: 7 +--- + +# Браузер + +Эти методы относятся к системному браузеру. + +### BrowserOpenURL + +Открывает данный URL-адрес в системном браузере. + +Go: `BrowserOpenURL(ctx context.Context, url string)`
JS: `BrowserOpenURL(url string)` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx new file mode 100644 index 00000000000..805f68ed917 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx @@ -0,0 +1,23 @@ +--- +sidebar_position: 8 +--- + +# Clipboard + +This part of the runtime provides access to the operating system's clipboard.
The current implementation only handles text. + +### ClipboardGetText + +This method reads the currently stored text from the clipboard. + +Go: `ClipboardGetText(ctx context.Context) (string, error)`
Returns: a string (if the clipboard is empty an empty string will be returned) or an error. + +JS: `ClipboardGetText(): Promise`
Returns: a promise with a string result (if the clipboard is empty an empty string will be returned). + +### ClipboardSetText + +This method writes a text to the clipboard. + +Go: `ClipboardSetText(ctx context.Context, text string) error`
Returns: an error if there is any. + +JS: `ClipboardSetText(text: string): Promise`
Returns: a promise with true result if the text was successfully set on the clipboard, false otherwise. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx new file mode 100644 index 00000000000..9b3e6cf145c --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx @@ -0,0 +1,302 @@ +--- +sidebar_position: 5 +--- + +# Dialog + +This part of the runtime provides access to native dialogs, such as File Selectors and Message boxes. + +:::info JavaScript + +Dialog is currently unsupported in the JS runtime. + +::: + +### OpenDirectoryDialog + +Opens a dialog that prompts the user to select a directory. Can be customised using [OpenDialogOptions](#opendialogoptions). + +Go: `OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)` + +Returns: Selected directory (blank if the user cancelled) or an error + +### OpenFileDialog + +Opens a dialog that prompts the user to select a file. Can be customised using [OpenDialogOptions](#opendialogoptions). + +Go: `OpenFileDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)` + +Returns: Selected file (blank if the user cancelled) or an error + +### OpenMultipleFilesDialog + +Opens a dialog that prompts the user to select multiple files. Can be customised using [OpenDialogOptions](#opendialogoptions). + +Go: `OpenMultipleFilesDialog(ctx context.Context, dialogOptions OpenDialogOptions) ([]string, error)` + +Returns: Selected files (nil if the user cancelled) or an error + +### SaveFileDialog + +Opens a dialog that prompts the user to select a filename for the purposes of saving. Can be customised using [SaveDialogOptions](#savedialogoptions). + +Go: `SaveFileDialog(ctx context.Context, dialogOptions SaveDialogOptions) (string, error)` + +Returns: The selected file (blank if the user cancelled) or an error + +### MessageDialog + +Displays a message using a message dialog. Can be customised using [MessageDialogOptions](#messagedialogoptions). + +Go: `MessageDialog(ctx context.Context, dialogOptions MessageDialogOptions) (string, error)` + +Returns: The text of the selected button or an error + +## Options + +### OpenDialogOptions + +```go +type OpenDialogOptions struct { + DefaultDirectory string + DefaultFilename string + Title string + Filters []FileFilter + ShowHiddenFiles bool + CanCreateDirectories bool + ResolvesAliases bool + TreatPackagesAsDirectories bool +} +``` + +| Field | Description | Win | Mac | Lin | +| -------------------------- | ---------------------------------------------- | --- | --- | --- | +| DefaultDirectory | The directory the dialog will show when opened | ✅ | ✅ | ✅ | +| DefaultFilename | The default filename | ✅ | ✅ | ✅ | +| Title | Title for the dialog | ✅ | ✅ | ✅ | +| [Filters](#filefilter) | A list of file filters | ✅ | ✅ | ✅ | +| ShowHiddenFiles | Show files hidden by the system | | ✅ | ✅ | +| CanCreateDirectories | Allow user to create directories | | ✅ | | +| ResolvesAliases | If true, returns the file not the alias | | ✅ | | +| TreatPackagesAsDirectories | Allow navigating into packages | | ✅ | | + +### SaveDialogOptions + +```go +type SaveDialogOptions struct { + DefaultDirectory string + DefaultFilename string + Title string + Filters []FileFilter + ShowHiddenFiles bool + CanCreateDirectories bool + TreatPackagesAsDirectories bool +} +``` + +| Field | Description | Win | Mac | Lin | +| -------------------------- | ---------------------------------------------- | --- | --- | --- | +| DefaultDirectory | The directory the dialog will show when opened | ✅ | ✅ | ✅ | +| DefaultFilename | The default filename | ✅ | ✅ | ✅ | +| Title | Title for the dialog | ✅ | ✅ | ✅ | +| [Filters](#filefilter) | A list of file filters | ✅ | ✅ | ✅ | +| ShowHiddenFiles | Show files hidden by the system | | ✅ | ✅ | +| CanCreateDirectories | Allow user to create directories | | ✅ | | +| TreatPackagesAsDirectories | Allow navigating into packages | | ✅ | | + +### MessageDialogOptions + +```go +type MessageDialogOptions struct { + Type DialogType + Title string + Message string + Buttons []string + DefaultButton string + CancelButton string +} +``` + +| Field | Description | Win | Mac | Lin | +| ------------- | -------------------------------------------------------------------------- | -------------- | --- | --- | +| Type | The type of message dialog, eg question, info... | ✅ | ✅ | ✅ | +| Title | Title for the dialog | ✅ | ✅ | ✅ | +| Message | The message to show the user | ✅ | ✅ | ✅ | +| Buttons | A list of button titles | | ✅ | | +| DefaultButton | The button with this text should be treated as default. Bound to `return`. | ✅[*](#windows) | ✅ | | +| CancelButton | The button with this text should be treated as cancel. Bound to `escape` | | ✅ | | + +#### Windows + +Windows has standard dialog types in which the buttons are not customisable. The value returned will be one of: "Ok", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No", "Try Again" or "Continue". + +For Question dialogs, the default button is "Yes" and the cancel button is "No". This can be changed by setting the `DefaultButton` value to `"No"`. + +Example: +```go + result, err := runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Question", + Message: "Do you want to continue?", + DefaultButton: "No", + }) +``` + +#### Linux + +Linux has standard dialog types in which the buttons are not customisable. The value returned will be one of: "Ok", "Cancel", "Yes", "No" + +#### Mac + +A message dialog on Mac may specify up to 4 buttons. If no `DefaultButton` or `CancelButton` is given, the first button is considered default and is bound to the `return` key. + +For the following code: + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, +}) +``` + +the first button is shown as default: + +```mdx-code-block +
+ +
+
+``` + +And if we specify `DefaultButton` to be "two": + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, + DefaultButton: "two", +}) +``` + +the second button is shown as default. When `return` is pressed, the value "two" is returned. + +```mdx-code-block +
+ +
+
+``` + +If we now specify `CancelButton` to be "three": + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, + DefaultButton: "two", + CancelButton: "three", +}) +``` + +the button with "three" is shown at the bottom of the dialog. When `escape` is pressed, the value "three" is returned: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### DialogType + +```go +const ( + InfoDialog DialogType = "info" + WarningDialog DialogType = "warning" + ErrorDialog DialogType = "error" + QuestionDialog DialogType = "question" + ) +``` + +### FileFilter + +```go +type FileFilter struct { + DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)" + Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png" +} +``` + +#### Windows + +Windows allows you to use multiple file filters in dialog boxes. Each FileFilter will show up as a separate entry in the dialog: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### Linux + +Linux allows you to use multiple file filters in dialog boxes. Each FileFilter will show up as a separate entry in the dialog: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### Mac + +Mac dialogs only have the concept of a single set of patterns to filter files. If multiple FileFilters are provided, Wails will use all the Patterns defined. + +Example: + +```go + selection, err := runtime.OpenFileDialog(b.ctx, runtime.OpenDialogOptions{ + Title: "Select File", + Filters: []runtime.FileFilter{ + { + DisplayName: "Images (*.png;*.jpg)", + Pattern: "*.png;*.jpg", + }, { + DisplayName: "Videos (*.mov;*.mp4)", + Pattern: "*.mov;*.mp4", + }, + }, + }) +``` + +This will result in the Open File dialog using `*.png,*.jpg,*.mov,*.mp4` as a filter. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx new file mode 100644 index 00000000000..856ba6f0c26 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx @@ -0,0 +1,37 @@ +--- +sidebar_position: 2 +--- + +# Events + +The Wails runtime provides a unified events system, where events can be emitted or received by either Go or JavaScript. Optionally, data may be passed with the events. Listeners will receive the data in the local data types. + +### EventsOn + +This method sets up a listener for the given event name. When an event of type `eventName` is [emitted](#EventsEmit), the callback is triggered. Any additional data sent with the emitted event will be passed to the callback. It returns a function to cancel the listener. + +Go: `EventsOn(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`
JS: `EventsOn(eventName string, callback function(optionalData?: any)): () => void` + +### EventsOff + +This method unregisters the listener for the given event name, optionally multiple listeneres can be unregistered via `additionalEventNames`. + +Go: `EventsOff(ctx context.Context, eventName string, additionalEventNames ...string)`
JS: `EventsOff(eventName string, ...additionalEventNames)` + +### EventsOnce + +This method sets up a listener for the given event name, but will only trigger once. It returns a function to cancel the listener. + +Go: `EventsOnce(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`
JS: `EventsOnce(eventName string, callback function(optionalData?: any)): () => void` + +### EventsOnMultiple + +This method sets up a listener for the given event name, but will only trigger a maximum of `counter` times. It returns a function to cancel the listener. + +Go: `EventsOnMultiple(ctx context.Context, eventName string, callback func(optionalData ...interface{}), counter int) func()`
JS: `EventsOnMultiple(eventName string, callback function(optionalData?: any), counter int): () => void` + +### EventsEmit + +This method emits the given event. Optional data may be passed with the event. This will trigger any event listeners. + +Go: `EventsEmit(ctx context.Context, eventName string, optionalData ...interface{})`
JS: `EventsEmit(eventName: string, ...optionalData: any)` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx new file mode 100644 index 00000000000..aae8efccccf --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx @@ -0,0 +1,85 @@ +--- +sidebar_position: 1 +--- + +# Introduction + +The runtime is a library that provides utility methods for your application. There is both a Go and JavaScript runtime and the aim is to try and keep them at parity where possible. + +It has utility methods for: + +- [Window](window.mdx) +- [Menu](menu.mdx) +- [Dialog](dialog.mdx) +- [Events](events.mdx) +- [Browser](browser.mdx) +- [Log](log.mdx) +- [Clipboard](clipboard.mdx) + +The Go Runtime is available through importing `github.com/wailsapp/wails/v2/pkg/runtime`. All methods in this package take a context as the first parameter. This context should be obtained from the [OnStartup](../options.mdx#onstartup) or [OnDomReady](../options.mdx#ondomready) hooks. + +:::info Note + +Whilst the context will be provided to the [OnStartup](../options.mdx#onstartup) method, there's no guarantee the runtime will work in this method as the window is initialising in a different thread. If you wish to call runtime methods at startup, use [OnDomReady](../options.mdx#ondomready). + +::: + +The JavaScript library is available to the frontend via the `window.runtime` map. There is a runtime package generated when using `dev` mode that provides TypeScript declarations for the runtime. This should be located in the `wailsjs` directory in your frontend directory. + +### Hide + +Go: `Hide(ctx context.Context)`
JS: `Hide()` + +Hides the application. + +:::info Note + +On Mac, this will hide the application in the same way as the `Hide` menu item in standard Mac applications. This is different to hiding the window, but the application still being in the foreground. For Windows and Linux, this is currently the same as `WindowHide`. + +::: + +### Show + +Shows the application. + +:::info Note + +On Mac, this will bring the application back into the foreground. For Windows and Linux, this is currently the same as `WindowShow`. + +::: + +Go: `Show(ctx context.Context)`
JS: `Show()` + +### Quit + +Quits the application. + +Go: `Quit(ctx context.Context)`
JS: `Quit()` + +### Environment + +Returns details of the current environment. + +Go: `Environment(ctx context.Context) EnvironmentInfo`
JS: `Environment(): Promise` + +#### EnvironmentInfo + +Go: + +```go +type EnvironmentInfo struct { + BuildType string + Platform string + Arch string +} +``` + +JS: + +```ts +interface EnvironmentInfo { + buildType: string; + platform: string; + arch: string; +} +``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx new file mode 100644 index 00000000000..06f0423b0a8 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 3 +--- + +# Log + +The Wails runtime provides a logging mechanism that may be called from Go or JavaScript. Like most loggers, there are a number of log levels: + +- Trace +- Debug +- Info +- Warning +- Error +- Fatal + +The logger will output any log message at the current, or higher, log level. Example: The `Debug` log level will output all messages except `Trace` messages. + +### LogPrint + +Logs the given message as a raw message. + +Go: `LogPrint(ctx context.Context, message string)`
JS: `LogPrint(message: string)` + +### LogPrintf + +Logs the given message as a raw message. + +Go: `LogPrintf(ctx context.Context, format string, args ...interface{})`
+ +### LogTrace + +Logs the given message at the `Trace` log level. + +Go: `LogTrace(ctx context.Context, message string)`
JS: `LogTrace(message: string)` + +### LogTracef + +Logs the given message at the `Trace` log level. + +Go: `LogTracef(ctx context.Context, format string, args ...interface{})`
+ +### LogDebug + +Logs the given message at the `Debug` log level. + +Go: `LogDebug(ctx context.Context, message string)`
JS: `LogDebug(message: string)` + +### LogDebugf + +Logs the given message at the `Debug` log level. + +Go: `LogDebugf(ctx context.Context, format string, args ...interface{})`
+ +### LogInfo + +Logs the given message at the `Info` log level. + +Go: `LogInfo(ctx context.Context, message string)`
JS: `LogInfo(message: string)` + +### LogInfof + +Logs the given message at the `Info` log level. + +Go: `LogInfof(ctx context.Context, format string, args ...interface{})`
+ +### LogWarning + +Logs the given message at the `Warning` log level. + +Go: `LogWarning(ctx context.Context, message string)`
JS: `LogWarning(message: string)` + +### LogWarningf + +Logs the given message at the `Warning` log level. + +Go: `LogWarningf(ctx context.Context, format string, args ...interface{})`
+ +### LogError + +Logs the given message at the `Error` log level. + +Go: `LogError(ctx context.Context, message string)`
JS: `LogError(message: string)` + +### LogErrorf + +Logs the given message at the `Error` log level. + +Go: `LogErrorf(ctx context.Context, format string, args ...interface{})`
+ +### LogFatal + +Logs the given message at the `Fatal` log level. + +Go: `LogFatal(ctx context.Context, message string)`
JS: `LogFatal(message: string)` + +### LogFatalf + +Logs the given message at the `Fatal` log level. + +Go: `LogFatalf(ctx context.Context, format string, args ...interface{})`
+ +### LogSetLogLevel + +Sets the log level. In JavaScript, the number relates to the following log levels: + +| Value | Log Level | +| ----- | --------- | +| 1 | Trace | +| 2 | Debug | +| 3 | Info | +| 4 | Warning | +| 5 | Error | + +Go: `LogSetLogLevel(ctx context.Context, level logger.LogLevel)`
JS: `LogSetLogLevel(level: number)` + +## Using a Custom Logger + +A custom logger may be used by providing it using the [Logger](../options.mdx#logger) application option. The only requirement is that the logger implements the `logger.Logger` interface defined in `github.com/wailsapp/wails/v2/pkg/logger`: + +```go title="logger.go" +type Logger interface { + Print(message string) + Trace(message string) + Debug(message string) + Info(message string) + Warning(message string) + Error(message string) + Fatal(message string) +} +``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx new file mode 100644 index 00000000000..6b6ceb77d69 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx @@ -0,0 +1,25 @@ +--- +sidebar_position: 6 +--- + +# Меню + +Эти методы относятся к меню приложения. + +:::info JavaScript + +В настоящее время меню не поддерживается в JS. + +::: + +### MenuSetApplicationMenu + +Задает меню приложения для данного [меню](../menus.mdx). + +Go: `MenuSetApplicationMenu(ctx context.Context, menu *menu.Menu)` + +### MenuUpdateApplicationMenu + +Обновляет меню приложения, поднимая все изменения в меню, переданное `MenuSetationMenu`. + +Go: `MenuUpdateApplicationMenu(ctx context.Context)` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx new file mode 100644 index 00000000000..457c92ebff9 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx @@ -0,0 +1,38 @@ +--- +sidebar_position: 9 +--- + +# Screen + +These methods provide information about the currently connected screens. + +### ScreenGetAll + +Returns a list of currently connected screens. + +Go: `ScreenGetAll(ctx context.Context) []screen`
+JS: `ScreenGetAll()` + +#### Screen + +Go struct: + +```go +type Screen struct { + IsCurrent bool + IsPrimary bool + Width int + Height int +} +``` + +Typescript interface: + +```ts +interface Screen { + isCurrent: boolean; + isPrimary: boolean; + width : number + height : number +} +``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx new file mode 100644 index 00000000000..15f555c5a79 --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx @@ -0,0 +1,227 @@ +--- +sidebar_position: 4 +--- + +# Window + +These methods give control of the application window. + +### WindowSetTitle + +Sets the text in the window title bar. + +Go: `WindowSetTitle(ctx context.Context, title string)`
JS: `WindowSetTitle(title: string)` + +### WindowFullscreen + +Makes the window full screen. + +Go: `WindowFullscreen(ctx context.Context)`
JS: `WindowFullscreen()` + +### WindowUnfullscreen + +Restores the previous window dimensions and position prior to full screen. + +Go: `WindowUnfullscreen(ctx context.Context)`
JS: `WindowUnfullscreen()` + +### WindowIsFullscreen + +Returns true if the window is full screen. + +Go: `WindowIsFullscreen(ctx context.Context) bool`
JS: `WindowIsFullscreen() bool` + +### WindowCenter + +Centers the window on the monitor the window is currently on. + +Go: `WindowCenter(ctx context.Context)`
JS: `WindowCenter()` + +### WindowExecJS + +Executes arbitrary JS code in the window. + +This method runs the code in the browser asynchronously and returns immediately. If the script causes any errors, they will only be available in the browser console. + +Go: `WindowExecJS(ctx context.Context, js string)` + +### WindowReload + +Performs a "reload" (Reloads current page). + +Go: `WindowReload(ctx context.Context)`
JS: `WindowReload()` + +### WindowReloadApp + +Reloads the application frontend. + +Go: `WindowReloadApp(ctx context.Context)`
JS: `WindowReloadApp()` + +### WindowSetSystemDefaultTheme + +Windows only. + +Go: `WindowSetSystemDefaultTheme(ctx context.Context)`
JS: `WindowSetSystemDefaultTheme()` + +Sets window theme to system default (dark/light). + +### WindowSetLightTheme + +Windows only. + +Go: `WindowSetLightTheme(ctx context.Context)`
JS: `WindowSetLightTheme()` + +Sets window theme to light. + +### WindowSetDarkTheme + +Windows only. + +Go: `WindowSetDarkTheme(ctx context.Context)`
JS: `WindowSetDarkTheme()` + +Sets window theme to dark. + +### WindowShow + +Shows the window, if it is currently hidden. + +Go: `WindowShow(ctx context.Context)`
JS: `WindowShow()` + +### WindowHide + +Hides the window, if it is currently visible. + +Go: `WindowHide(ctx context.Context)`
JS: `WindowHide()` + +### WindowIsNormal + +Returns true if the window not minimised, maximised or fullscreen. + +Go: `WindowIsNormal(ctx context.Context) bool`
JS: `WindowIsNormal() bool` + +### WindowSetSize + +Sets the width and height of the window. + +Go: `WindowSetSize(ctx context.Context, width int, height int)`
JS: `WindowSetSize(width: number, height: number)` + +### WindowGetSize + +Gets the width and height of the window. + +Go: `WindowGetSize(ctx context.Context) (width int, height int)`
JS: `WindowGetSize() : Size` + +### WindowSetMinSize + +Sets the minimum window size. Will resize the window if the window is currently smaller than the given dimensions. + +Setting a size of `0,0` will disable this constraint. + +Go: `WindowSetMinSize(ctx context.Context, width int, height int)`
JS: `WindowSetMinSize(width: number, height: number)` + +### WindowSetMaxSize + +Sets the maximum window size. Will resize the window if the window is currently larger than the given dimensions. + +Setting a size of `0,0` will disable this constraint. + +Go: `WindowSetMaxSize(ctx context.Context, width int, height int)`
JS: `WindowSetMaxSize(width: number, height: number)` + +### WindowSetAlwaysOnTop + +Sets the window AlwaysOnTop or not on top. + +Go: `WindowSetAlwaysOnTop(ctx context.Context, b bool)`
JS: `WindowSetAlwaysOnTop(b: Boolen)` + +### WindowSetPosition + +Sets the window position relative to the monitor the window is currently on. + +Go: `WindowSetPosition(ctx context.Context, x int, y int)`
JS: `WindowSetPosition(x: number, y: number)` + +### WindowGetPosition + +Gets the window position relative to the monitor the window is currently on. + +Go: `WindowGetPosition(ctx context.Context) (x int, y int)`
JS: `WindowGetPosition() : Position` + +### WindowMaximise + +Maximises the window to fill the screen. + +Go: `WindowMaximise(ctx context.Context)`
JS: `WindowMaximise()` + +### WindowUnmaximise + +Restores the window to the dimensions and position prior to maximising. + +Go: `WindowUnmaximise(ctx context.Context)`
JS: `WindowUnmaximise()` + +### WindowIsMaximised + +Returns true if the window is maximised. + +Go: `WindowIsMaximised(ctx context.Context) bool`
JS: `WindowIsMaximised() bool` + +### WindowToggleMaximise + +Toggles between Maximised and UnMaximised. + +Go: `WindowToggleMaximise(ctx context.Context)`
JS: `WindowToggleMaximise()` + +### WindowMinimise + +Minimises the window. + +Go: `WindowMinimise(ctx context.Context)`
JS: `WindowMinimise()` + +### WindowUnminimise + +Restores the window to the dimensions and position prior to minimising. + +Go: `WindowUnminimise(ctx context.Context)`
JS: `WindowUnminimise()` + +### WindowIsMinimised + +Returns true if the window is minimised. + +Go: `WindowIsMinimised(ctx context.Context) bool`
JS: `WindowIsMinimised() bool` + +### WindowSetBackgroundColour + +Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels. + +Valid values for R, G, B and A are 0-255. + +:::info Windows + +On Windows, only alpha values of 0 or 255 are supported. Any value that is not 0 will be considered 255. + +::: + +Go: `WindowSetBackgroundColour(ctx context.Context, R, G, B, A uint8)`
JS: `WindowSetBackgroundColour(R, G, B, A)` + +### WindowPrint + +Opens tha native print dialog. + +Go: `WindowPrint(ctx context.Context)`
JS: `WindowPrint()` + +## TypeScript Object Definitions + +### Position + +```ts +interface Position { + x: number; + y: number; +} +``` + +### Size + +```ts +interface Size { + w: number; + h: number; +} +``` diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx new file mode 100644 index 00000000000..1af16f7745a --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx @@ -0,0 +1,245 @@ +--- +sidebar_position: 20 +--- + +# Dogs API + +```mdx-code-block +
+ +
+
+``` + +:::note + +This tutorial has been kindly provided by [@tatadan](https://twitter.com/tatadan) and forms part of their [Wails Examples Repository](https://github.com/tataDan/wails-v2-examples). + +::: + +In this tutorial we are going to develop an application that retrieves photos of dogs from the web and then displays them. + +### Create the project + +Let's create the application. From a terminal enter: `wails init -n dogs-api -t svelte` + +Note: We could optionally add `-ide vscode` or `-ide goland` to the end of this command if you wanted to add IDE support. + +Now let's `cd dogs-api` and start editing the project files. + +### Remove unused code + +We will start by removing some elements that we know we will not use: + +- Open `app.go` and remove the following lines: + +```go +// Greet returns a greeting for the given name +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s, It's show time!", name) +} +``` + +- Open `frontend/src/App.svelte` and delete all lines. +- Delete the `frontend/src/assets/images/logo-universal.png` file + +### Creating our application + +Now let's add our new Go code. + +Add the following struct declarations to `app.go` before the function definitions: + +```go +type RandomImage struct { + Message string + Status string +} + +type AllBreeds struct { + Message map[string]map[string][]string + Status string +} + +type ImagesByBreed struct { + Message []string + Status string +} +``` + +Add the following functions to `app.go` (perhaps after the existing function definitions): + +```go +func (a *App) GetRandomImageUrl() string { + response, err := http.Get("https://dog.ceo/api/breeds/image/random") + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data RandomImage + json.Unmarshal(responseData, &data) + + return data.Message +} + +func (a *App) GetBreedList() []string { + var breeds []string + + response, err := http.Get("https://dog.ceo/api/breeds/list/all") + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data AllBreeds + json.Unmarshal(responseData, &data) + + for k := range data.Message { + breeds = append(breeds, k) + } + + sort.Strings(breeds) + + return breeds +} + +func (a *App) GetImageUrlsByBreed(breed string) []string { + + url := fmt.Sprintf("%s%s%s%s", "https://dog.ceo/api/", "breed/", breed, "/images") + response, err := http.Get(url) + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data ImagesByBreed + json.Unmarshal(responseData, &data) + + return data.Message +} +``` + +Modify the `import` section of `app.go` to look like this: + +```go +import ( + "context" + "fmt" + "encoding/json" + "io/ioutil" + "log" + "net/http" + "sort" +) +``` + +Add the following lines to `frontend/src/App.svelte`: + + +```html + + +

Dogs API

+
+ + Click on down arrow to select a breed + + +
+
+{#if showRandomPhoto} + No dog found +{/if} +{#if showBreedPhotos} + {#each photos as photo} + No dog found + {/each} +{/if} + + +``` + + +### Testing the application + +To generate the bindings and test the application, run `wails dev`. + +### Compiling the application + +To compile the application to a single, production grade binary, run `wails build`. diff --git a/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx new file mode 100644 index 00000000000..77d128b188c --- /dev/null +++ b/website/i18n/ru/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx @@ -0,0 +1,123 @@ +--- +sidebar_position: 10 +--- + +# Hello World + +Цель этого урока — запустить наиболее базовое приложение, использующее Wails. Вы сможете: + +- Создавать новое Wails приложение +- Собирать приложение +- Запускать приложение + +:::note + +В этом уроке в качестве целевой платформы используется Windows. Вывод будет варьироваться в зависимости от вашей операционной системы. + +::: + +## Создаем новое Wails приложение + +Чтобы создать новое Wails приложение, использующее стандартный шаблон JS, вам нужно выполнить следующую команду: + +```bash +wails init -n helloworld +``` + +Вы должны увидеть что-то похожее на следующее: + +``` +Wails CLI v2.0.0 + +Initialising Project 'helloworld' +--------------------------------- + +Project Name: helloworld +Project Directory: C:\Users\leaan\tutorial\helloworld +Project Template: vanilla +Template Support: https://wails.io + +Initialised project 'helloworld' in 232ms. +``` + +Это создаст новый каталог под названием `helloworld` в текущей директории. В этом каталоге вы найдете несколько файлов: + +``` +build/ - Contains the build files + compiled application +frontend/ - Contains the frontend files +app.go - Contains the application code +main.go - The main program with the application configuration +wails.json - The project configuration file +go.mod - The go module file +go.sum - The go module checksum file +``` + +## Сборка приложения + +Чтобы собрать приложение, перейдите в новую директорию `helloworld` и запустите следующую команду: + +```bash +wails build +``` + +Вы должны увидеть что-то похожее на следующее: + +``` +Wails CLI v2.0.0 + +App Type: desktop +Platforms: windows/amd64 +Compiler: C:\Users\leaan\go\go1.18.3\bin\go.exe +Build Mode: Production +Devtools: false +Skip Frontend: false +Compress: false +Package: true +Clean Build Dir: false +LDFlags: "" +Tags: [] +Race Detector: false + +Building target: windows/amd64 +------------------------------ + - Installing frontend dependencies: Done. + - Compiling frontend: Done. + - Generating bundle assets: Done. + - Compiling application: Done. +Built 'C:\Users\leaan\tutorial\helloworld\build\bin\helloworld.exe' in 10.616s. +``` + +Приложение собрано и сохранено в папке `build/bin`. + +## Запуск приложения + +Если мы откроем папку `build/bin` в Проводнике, то увидим исполняемый файл проекта: + +```mdx-code-block +
+ +
+
+``` + +Мы можем запустить его, просто дважды щелкнув по файлу `helloworld.exe`. + +На Mac, Wails генерирует файл `helloworld.app` который может быть запущен двойным щелчком. + +На Linux вы можете запустить приложение с помощью файла `./helloworld` из папки `build/bin`. + +Вы должны видеть приложение, работающее так, как ожидалось: + +```mdx-code-block +
+ +
+
+``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/appendix/_category_.json b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/appendix/_category_.json new file mode 100644 index 00000000000..1374f0d5518 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/appendix/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Runtime", + "position": 70 +} diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/_category_.json b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/_category_.json new file mode 100644 index 00000000000..9827bf0c0fb --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "社区", + "position": 50 +} diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx new file mode 100644 index 00000000000..8f8a54fcb3d --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/links.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 2 +--- + +# 链接 + +此页面用于列出社区相关的链接。 请提交 PR(点击页面底部的 `编辑此页`)增加链接。 + +## Awesome Wails + +Wails 相关的 [优秀列表](https://github.com/wailsapp/awesome-wails)。 + +## 支持的频道 + +- [Wails Discord 服务器](https://discord.gg/JDdSxwjhGf) +- [Github Issues](https://github.com/wailsapp/wails/issues) +- [v2 测试版讨论板](https://github.com/wailsapp/wails/discussions/828) + +## 社交媒体 + +- [Twitter](https://twitter.com/wailsapp) +- [Wails 中文社区 QQ 群](https://qm.qq.com/cgi-bin/qm/qr?k=PmIURne5hFGNd7QWzW5qd6FV-INEjNJv&jump_from=webapi) - 群号:1067173054 + +## 其他教程和文章 + +- [Building of Bulletin Board](https://blog.customct.com/building-bulletin-board) diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/_category_.json b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/_category_.json new file mode 100644 index 00000000000..276e283b71f --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Showcase", + "position": 1 +} diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx new file mode 100644 index 00000000000..2bba85cb82d --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/bulletinboard.mdx @@ -0,0 +1,10 @@ +# BulletinBoard + +```mdx-code-block +

+ +
+

+``` + +[BulletinBoard](https://github.com/raguay/BulletinBoard) 应用程序是一个用于静态消息或对话框的通用消息板,用于获取用户的脚本信息。 它有一个用于创建新对话框的 TUI,后者可以使用这些对话框从用户那里获取信息。 它的设计是在您的系统上保持运行并根据需要显示信息,然后隐藏起来。 我有一个在我的系统上监视文件并在更改时将内容发送到 BulletinBoard 的进程。 它与我的工作流配合的很好。 还有一个用于向程序发送信息的 [Alfred 工作流](https://github.com/raguay/MyAlfred/blob/master/Alfred%205/EmailIt.alfredworkflow)。 该工作流也适用于 [EmailIt](https://github.com/raguay/EmailIt)。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx new file mode 100644 index 00000000000..5e1597d70af --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/cfntracker.mdx @@ -0,0 +1,35 @@ +# CFN Tracker + +```mdx-code-block +

+ +
+

+``` + +[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - 跟踪任何《街头霸 +王 6》或 V CFN 个人资料的实时比赛。 检查[网站](https://cfn.williamsjokvist.se/) +开始。 + +## 特征 + +- 实时比赛追踪 +- 存储比赛日志和统计数据 +- 支持通过浏览器源向 OBS 显示实时统计数据 +- 支持 SF6 和 SFV +- 用户能够使用 CSS 创建自己的 OBS 浏览器主题 + +### 与 Wails 一起使用的主要技术 + +- [Task](https://github.com/go-task/task) - 包装 Wails CLI 以使常用命令易于使用 +- [React](https://github.com/facebook/react) - 因其丰富的生态系统而被选中 + (radix、framer-motion) +- [Bun](https://github.com/oven-sh/bun) - 用于快速依赖解析和构建时间 +- [Rod](https://github.com/go-rod/rod) - 用于身份验证和轮询更改的无头浏览器自动 + 化 +- [SQLite](https://github.com/mattn/go-sqlite3) - 用于存储匹配、会话和配置文件 +- [服务器发送事件](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - + 用于向 OBS 浏览器源发送跟踪更新的 http 流 +- [i18next](https://github.com/i18next/) - 使用后端连接器来服务来自 Go 层的本地 + 化对象 +- [xstate](https://github.com/statelyai/xstate) - 用于身份验证过程和跟踪的状态机 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx new file mode 100644 index 00000000000..701e96b5a95 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/emailit.mdx @@ -0,0 +1,10 @@ +# EmailIt + +```mdx-code-block +

+ +
+

+``` + +[EmailIt](https://github.com/raguay/EmailIt/) 是一个 Wails v2 程序,它是一个基于 Markdown 的电子邮件发送器,只有九个记事本、用于处理文本的脚本和模板。 它还有一个脚本终端,用于在 EmailIt 中对系统中的文件运行脚本。 脚本和模板可以从命令行本身使用,也可以与 Alfred、Keyboard Maestro、Dropzone 或 PopClip 扩展一起使用。 它还支持从 GitHub 下载的脚本和主题。 文档不完整,但程序有效。 它是使用 Wails v2 和 Svelte 构建的,下载的是一个通用的 macOS 应用程序。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx new file mode 100644 index 00000000000..df788c69cbd --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/encrypteasy.mdx @@ -0,0 +1,12 @@ +# EncryptEasy + +```mdx-code-block +

+ +
+

+``` + +**[EncryptEasy](https://www.encrypteasy.app) 是一个简单易用的 PGP 加密工具,管理您和您的所有联系人密钥。 加密应该很简单。 使用 Wails 开发。** + +使用 PGP 加密消息是行业标准。 每个人都有私钥和公钥。 您的私钥需要保密,因此只有您可以阅读消息。 您的公钥会分发给任何想向您发送秘密加密消息的人。 管理密钥、加密消息和解密消息应该是一种流畅的体验。 EncryptEasy 就是要让它变得简单。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx new file mode 100644 index 00000000000..43f3289181e --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/espstudio.mdx @@ -0,0 +1,13 @@ +# ESP Studio + +```mdx-code-block +

+ +
+

+``` + +[ESP Studio](https://github.com/torabian/esp-studio) - 跨平台、桌面、云和嵌入式软件 +用于控制 ESP/Arduino 设备,以及构建复杂的物联网工作流程和控制系统 \ No newline at end of file diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx new file mode 100644 index 00000000000..a0566cccf7a --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/filehound.mdx @@ -0,0 +1,16 @@ +# FileHound Export Utility + +```mdx-code-block +

+ +
+

+``` + +[FileHound Export Utility](https://www.filehound.co.uk/) FileHound 是一个云文档管理平台,用于安全文件保留、业务流程自动化和 SmartCapture 功能。 + +FileHound Export Utility 允许 FileHound 管理员运行安全文档和数据提取任务以备选备份和恢复目的。 此应用程序将根据您选择的过滤器下载保存在 FileHound 中的所有文档和/或元数据。 元数据将以 JSON 和 XML 格式导出。 + +后端构建使用:Go 1.15 Wails 1.11.0 go-sqlite3 1.14.6 go-linq 3.2 + +前端使用:Vue 2.6.11 Vuex 3.4.0 TypeScript Tailwind 1.9.6 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx new file mode 100644 index 00000000000..61153563564 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/hiposter.mdx @@ -0,0 +1,10 @@ +# hiposter + +```mdx-code-block +

+ +
+

+``` + +[hiposter](https://github.com/obity/hiposter) 是一个简单高效的 HTTP API 测试客户端工具。 基于 Wails、Go 和 sveltejs。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx new file mode 100644 index 00000000000..f5552ed5ad7 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/minecraftupdater.mdx @@ -0,0 +1,14 @@ +# Minecraft Updater + +```mdx-code-block +

+ +
+

+``` + +[Minecraft Updater](https://github.com/Gurkengewuerz/MinecraftModUpdater) 是一个可以为你的用户更新和同步 Minecraft 模组的实用工具。 它使用 Wails2 和 React 构建,采用 [antd](https://ant.design/) 作为前端框架。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx new file mode 100644 index 00000000000..634ef3329bb --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/modalfilemanager.mdx @@ -0,0 +1,14 @@ +# Modal File Manager + +```mdx-code-block +

+ +
+

+``` + +[Modal File Manager](https://github.com/raguay/ModalFileManager) 是一个使用网络技术的双面板文件管理器。 我最初的设计是基于 NW.js 的,可以在 [这里](https://github.com/raguay/ModalFileManager-NWjs) 找到。 此版本使用相同的基于 Svelte 的前端代码(但自从 NW.js 脱离以来已进行了很大修改),但后端是 [Wails v2](https://wails.io/) 实现。 通过使用这个实现,我不再使用命令行 `rm`、`cp` 等命令,而是必须在系统上安装 git 才能下载主题和扩展。 它完全使用 Go 编码,运行速度比以前的版本快得多。 + +这个文件管理器是围绕与 Vim 相同的原则设计的:状态控制键盘操作。 状态的数量不是固定的,但非常可编程。 因此,可以创建和使用无数种键盘配置。 这是与其他文件管理器的主要区别。 可以从 GitHub 下载主题和扩展。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx new file mode 100644 index 00000000000..1df94bb1139 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/mollywallet.mdx @@ -0,0 +1,10 @@ +# Molley Wallet + +```mdx-code-block +

+ +
+

+``` + +[Molly Wallet](https://github.com/grvlle/constellation_wallet/) 是 Constellation 网络的官方 $DAG 钱包。 它允许用户以各种方式与 Hypergraph 网络进行交互,而不仅仅是产生 $DAG 交易。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx new file mode 100644 index 00000000000..861e8d43c2b --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/october.mdx @@ -0,0 +1,14 @@ +# October + +```mdx-code-block +

+ +
+

+``` + +[October](https://october.utf9k.net) 是一个小型的 Wails 应用程序,它可以非常容易地从 [Kobo eReaders](https://en.wikipedia.org/wiki/Kobo_eReader) 中提取精彩片段,然后将它们转发到 [Readwise](https://readwise.io) 。 + +它的代码规模相对较小,所有平台版本的大小都不到10 MB ,而且这还是在没有启用 [UPX 压缩](https://upx.github.io/) 的情况下! + +相比之下,作者之前尝试使用 Electron 很快就膨胀到了几百兆字节。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx new file mode 100644 index 00000000000..baea5ba9218 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/optimus.mdx @@ -0,0 +1,10 @@ +# Optimus + +```mdx-code-block +

+ +
+

+``` + +[Optimus](https://github.com/splode/optimus) 是一款桌面图像优化应用程序。 它支持 WebP、JPEG 和 PNG 图像格式之间的转换和压缩。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx new file mode 100644 index 00000000000..40180200bef --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/portfall.mdx @@ -0,0 +1,10 @@ +# Portfall + +```mdx-code-block +

+ +
+

+``` + +[Portfall](https://github.com/rekon-oss/portfall) - 桌面 k8s 端口转发门户,可轻松访问你的所有集群 UI 。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx new file mode 100644 index 00000000000..a7f07f4f5b6 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/restic-browser.mdx @@ -0,0 +1,12 @@ +# Restic Browser + +```mdx-code-block +

+ +
+

+``` + +[Restic-Browser](https://github.com/emuell/restic-browser) - 一个简单的、跨平台的 [restic](https://github.com/restic/restic) 备份 GUI ,用于浏览和恢复 restic 存储库。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx new file mode 100644 index 00000000000..29514c8e5ba --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/riftshare.mdx @@ -0,0 +1,21 @@ +# RiftShare + +```mdx-code-block +

+ +
+

+``` + +为每个人提供简单、安全和免费的文件共享。 请访问 [Riftshare.app](https://riftshare.app) 了解更多信息。 + +## 功能 + +- 可以在本地网络和互联网之间轻松安全地共享文件 +- 支持通过 [魔法虫洞(magic-wormhole)](https://magic-wormhole.readthedocs.io/en/latest/) 安全地发送文件或目录 +- 与所有其他使用魔法虫洞(magic-wormhole)的应用程序兼容( magic-wormhole 或 wormhole-william CLI,wormhole-gui 等。) +- 自动压缩多个选定文件以便一次性发送 +- 发送和接收的完整动画、进度条和取消支持 +- 原生的操作系统文件选择功能 +- 接收文件后一键打开 +- 自动更新 - 不用担心有最新的版本! diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx new file mode 100644 index 00000000000..85409d3c7bd --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/scriptbar.mdx @@ -0,0 +1,10 @@ +# ScriptBar + +```mdx-code-block +

+ +
+

+``` + +[ScriptBar](https://GitHub.com/raguay/ScriptBarApp) 是一个用于显示脚本或 [Node-Red](https://nodered.org) 服务器输出的程序。 它运行 EmailIt 程序中定义的脚本,并显示输出结果。 可以使用来自 xBar 或 TextBar 的脚本,但目前只有 TextBar 的脚本运行良好。 它还可以显示你系统中的脚本输出。 ScriptBar 并没有把它们放在菜单栏中,而是提供一个方便的窗口,方便用户查看。 你可以使用多个标签页来显示不同的内容。 还可以保留访问次数最多的网站链接。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx new file mode 100644 index 00000000000..67e0930beeb --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/surge.mdx @@ -0,0 +1,10 @@ +# Surge + +```mdx-code-block +

+ +
+

+``` + +[Surge](https://getsurge.io/) 是一个 P2P 文件共享应用程序,旨在利用区块链技术实现100%匿名文件传输。 Surge 是端到端加密的、去中心化的以及开源的。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx new file mode 100644 index 00000000000..e3124bab727 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/tinyrdm.mdx @@ -0,0 +1,11 @@ +# Tiny RDM + +```mdx-code-block +

+ + +
+

+``` + +The [Tiny RDM](https://redis.tinycraft.cc/) application is an open-source, modern lightweight Redis GUI. It has a beautful UI, intuitive Redis database management, and compatible with Windows, Mac, and Linux. It provides visual key-value data operations, supports various data decoding and viewing options, built-in console for executing commands, slow log queries and more. diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx new file mode 100644 index 00000000000..349b8ce215e --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wally.mdx @@ -0,0 +1,10 @@ +# Wally + +```mdx-code-block +

+ +
+

+``` + +[Wally](https://ergodox-ez.com/pages/wally) 是 [Ergodox](https://ergodox-ez.com/) 键盘的官方固件刷写程序。 它看起来很不错,并且是一个使用 Wails 实现的绝妙示例:结合了 Go 语言的强大功能和 Web 开发世界丰富的图形工具。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx new file mode 100644 index 00000000000..1172a8c3366 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/warmine.mdx @@ -0,0 +1,19 @@ +# WarMine Minecraft 启动器 + +```mdx-code-block +

+ + +
+

+``` + +[Warmine Minecraft 启动器](https://warmine.ru/) 是一款 Wails 应用,它使您可以轻松地加入服务器并管理您的游戏账户。 + +启动器能够下载游戏文件, 检查游戏的完整性,使用自定义选项从后端启动游戏。 + +前端使用 Svelte 编写, 整个启动器大小约 9MB 并支持 Windows 7-11. diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx new file mode 100644 index 00000000000..d8d74d360ad --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/wombat.mdx @@ -0,0 +1,10 @@ +# Wombat + +```mdx-code-block +

+ +
+

+``` + +[Wombat](https://github.com/rogchap/wombat) 是一个跨平台的 gRPC 客户端。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx new file mode 100644 index 00000000000..12cefd304f5 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/showcase/ytd.mdx @@ -0,0 +1,10 @@ +# Ytd + +```mdx-code-block +

+ +
+

+``` + +[Ytd](https://github.com/marcio199226/ytd/tree/v2-wails) 是一款可以从 YouTube 下载音乐,创建离线播放列表并与朋友分享的应用程序。你的朋友们可以播放你的播放列表或将其下载到本地离线收听,并且该应用程序还内置了播放器。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx new file mode 100644 index 00000000000..fb487e87c79 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/community/templates.mdx @@ -0,0 +1,69 @@ +--- +sidebar_position: 1 +--- + +# 模板 + +此页面用作社区支持的模板列表。 请提交一个包含您的模板的 PR(点击页面底部的 `编辑此页`)。 要构建您自己的模板,请参考 [模板](../guides/templates) 指南。 + +要使用这些模板,请运行 `wails init -n "您的项目名" -t [下面的链接[@版本]]` + +如果不带版本后缀,默认使用的是主分支代码模板。 如果带有版本后缀,则使用该版本对应标签的代码模板。 + +示例:`wails init -n "Your Project Name" -t https://github.com/misitebao/wails-template-vue` + +:::warning 注意 + +**Wails 项目不维护也不对第 3 方模板负责** + +如果您不确定某个模板,请检查 `package.json` 和 `wails.json` 中安装的模块和运行的脚本。 + +::: + +## Vue + +- [wails-template-vue](https://github.com/misitebao/wails-template-vue) - 基于 Vue 生态的 Wails 模板(集成 TypeScript、黑暗主题、国际化、单页路由、TailwindCSS) +- [wails-vite-vue-ts](https://github.com/codydbentley/wails-vite-vue-ts) - 使用 Vite 的 Vue 3 TypeScript(以及添加功能的说明) +- [wails-vite-vue-the-works](https://github.com/codydbentley/wails-vite-vue-the-works) - 使用 Vite, Vuex, Vue Router, Sass, 和 ESLint + Prettier 的 Vue 3 TypeScript +- [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - 使用 JavaScript + Quasar V2(Vue 3, Vite, Sass, Pinia, ESLint, Prettier)的模板 +- [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - 使用 TypeScript + Quasar V2(Vue 3、Vite、Sass、Pinia、ESLint、Prettier、带 <script setup> 的Composition API)的模板 +- [wails-template-naive](https://github.com/tk103331/wails-template-naive) - 基于 Naive UI(一款 Vue 3 组件库)的 Wails 模板 + +## Angular + +- [wails-template-angular](https://github.com/mateothegreat/wails-template-angular) - Angular 15+ 已打包并准备投入生产。 +- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - 带有 TypeScript, Sass, 热重载, 代码拆分和 i18n 的 Angular + +## React + +- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - 基于 reactjs 的模板 +- [wails-react-template](https://github.com/flin7/wails-react-template) - 基于 React 并支持实时开发模式的轻量级模板 +- [wails-vite-react-ts](https://github.com/lontten/wails-vite-react-ts) - 基于 Vite + React + TypeScript 的模板 +- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - 一个 React + TypeScript + Vite + TailwindCSS 模板 +- [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - A template with Vite, React, TypeScript, TailwindCSS, and shadcn/ui + +## Svelte + +- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - 基于 Svelte 的模板 +- [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - 使用 Svelte 和 Vite 的模板 +- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - 使用 Svelte 和 Vite 和 TailwindCSS v3 的模板 +- [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - An updated template using Svelte v4.2.0 and Vite with TailwindCSS v3.3.3 +- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - 基于 Next.js + TypeScript 的模板 + +## Solid + +- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-ts) - 使用 Solid + Ts + Vite 的模版。 +- [wails-template-vite-solid-js](https://github.com/xijaja/wails-template-solid-js) - 使用 Solid + Js + Vite 的模版。 + +## Elm + +- [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - 使用函数式编程和 **快速** 的热重载设置开发您的 GUI 应用程序 :tada: :rocket: +- [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - 结合 Elm + Tailwind CSS + Wails 的力量 :muscle: ! 支持热重载。 + +## HTMX + +- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - Use a unique combination of pure htmx for interactivity plus templ for creating components and forms + +## 纯 JavaScript (Vanilla) + +- [wails-pure-js-template](https://github.com/KiddoV/wails-pure-js-template) - 一个只有基本 JavaScript、HTML 和 CSS 的模板 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/developing-new-features.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/developing-new-features.mdx new file mode 100644 index 00000000000..9fc9025bd4b --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/developing-new-features.mdx @@ -0,0 +1,34 @@ +--- +sidebar_position: 20 +--- + +# 开发新功能 + +We are always keen to add features to Wails and expand on what the project can do. The process for adding new features are as follows: The process for adding new features are as follows: We are always keen to add features to Wails and expand on what the project can do. The process for adding new features are as follows: The process for adding new features are as follows: The process for adding new features are as follows: + +- Pick an enhancement ticket with the "TODO" label. Pick an enhancement ticket with the "TODO" label. Pick an enhancement ticket with the "TODO" label. It's preferable to select one from the current [Backlog](https://github.com/orgs/wailsapp/projects/1/views/1) but the choice is yours. +- Before developing, check that the ticket includes the following information: +- The purpose of the enhancement +- What is out of scope for the enhancement +- What platforms the enhancement targets (most features should be cross-platform unless there's a very specific reason) +- If the ticket does not include this information, feel free to request the information from the person who opened the ticket. Sometimes placeholder tickets are created and require more details Sometimes placeholder tickets are created and require more details Sometimes placeholder tickets are created and require more details +- Comment on the ticket stating you wish to develop the feature +- Clone the repository and create a branch with the format `feature/_` +- New features often require documentation so please ensure you have also added or updated the documentation as part of the changes +- Once the feature is ready for testing, create a draft PR. Once the feature is ready for testing, create a draft PR. Once the feature is ready for testing, create a draft PR. Please ensure the PR description has the test scenarios and test cases listed with checkmarks, so that others can know what still needs to be tested. Once the feature is ready for testing, create a draft PR. Once the feature is ready for testing, create a draft PR. Please ensure the PR description has the test scenarios and test cases listed with checkmarks, so that others can know what still needs to be tested. Once the feature is ready for testing, create a draft PR. Once the feature is ready for testing, create a draft PR. Please ensure the PR description has the test scenarios and test cases listed with checkmarks, so that others can know what still needs to be tested. +- Once all the testing is completed, please update the status of the PR from draft and leave a message. + +:::note +There is nothing stopping you from opening a ticket and working on it yourself, but please be aware that all +enhancement requests are reviewed for good fit. Not all ideas will be selected so it's best to have discussion +on the ticket first. +::: Not all ideas will be selected so it's best to have discussion +on the ticket first. +::: Not all ideas will be selected so it's best to have discussion +on the ticket first. +::: + +:::warning +Any PRs opened without a corresponding ticket may be rejected. +::: ::: +::: diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/documenting.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/documenting.mdx new file mode 100644 index 00000000000..84e47290358 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/documenting.mdx @@ -0,0 +1,34 @@ +--- +sidebar_position: 40 +--- + +# 文档 + +This website is also the main documentation site for the project. Sometimes this gets out of date and needs some slight adjustments. Some of the documentation isn't written to the best standards either. Developing documentation is hard and so any contribution to this is greatly appreciated. Features without documentation are unfinished so to the project, it's _as important_ as the code. + +We generally do not create tickets for updating documentation so if there is text you think should be updated or rephrased then feel free to submit a PR for that. This site is in the main repository under the `website` directory. We use [Docusaurus](https://docusaurus.io/) to create the site so there is plenty of existing documentation and tutorials around to get started. This site is in the main repository under the `website` directory. We use [Docusaurus](https://docusaurus.io/) to create the site so there is plenty of existing documentation and tutorials around to get started. This site is in the main repository under the `website` directory. We use [Docusaurus](https://docusaurus.io/) to create the site so there is plenty of existing documentation and tutorials around to get started. + +To set up a local documentation development environment, do the following: + +- [Install npm](https://docs.npmjs.com/cli/v8/configuring-npm/install) +- `cd website` +- `npm install` +- `npm run start` + +After it has all installed and is running, you should see the site at [`http://localhost:3000`](http://localhost:3000). Any changes made to the site text will be immediately reflected in the browser. Any changes made to the site text will be immediately reflected in the browser. Any changes made to the site text will be immediately reflected in the browser. + +## Versioning + +We employ a versioning system where we have the "latest" documentation AKA "Next Version" which has all the changes that have occurred since the last release. We also keep the last release documentation as well as the version before that. We also keep the last release documentation as well as the version before that. We also keep the last release documentation as well as the version before that. + +There isn't usually a reason to update released documentation so we don't generally update the documents in the `versioned_docs` or `versioned_sidebars` directories. + +The "next version" docs are mainly in `website/docs` with some "version independent" documents in `src/pages`. Any updates should be made in the `website/docs` directory. Any updates should be made in the `website/docs` directory. Any updates should be made in the `website/docs` directory. + +## Languages + +The default documents of the Wails project are English documents. We use the "crowdin" tool to translate documents in other languages and synchronize them to the website. You can [join our project](https://crowdin.com/project/wails) and submit your translations to make contributions. + +### Add new language + +If you want to add a new language to the documentation, please follow the prompts to [fill in and submit an Issue](https://github.com/wailsapp/wails/issues/new?assignees=&labels=documentation&template=documentation.yml). After being confirmed by the maintainer, we will add the language to the "crowdin" and you will then be able to submit your translation. diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/fixing-bugs.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/fixing-bugs.mdx new file mode 100644 index 00000000000..01eceeccd17 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/fixing-bugs.mdx @@ -0,0 +1,29 @@ +--- +sidebar_position: 30 +--- + +# 修复漏洞 + +The process for fixing bugs are as follows: + +- Check the current [Backlog](https://github.com/orgs/wailsapp/projects/1/views/1) and select a bug to fix +- Before developing, check that the ticket includes the following information: +- The scope of the issue including platforms affected +- The steps to reproduce. The steps to reproduce. The steps to reproduce. Sometimes bugs are opened that are not Wails issues and the onus is on the reporter to prove that it is a Wails issue with a minimal reproducible example +- The output of `wails doctor` +- If the ticket does not include this information, feel free to request the information from the person who opened the ticket. +- Comment on the ticket stating you wish to develop a fix +- Clone the repository and create a branch with the format `bugfix/_` +- Once the fix is ready for testing, create a draft PR. Once the fix is ready for testing, create a draft PR. Please ensure the PR description has the test scenarios and test cases listed with checkmarks, so that others can know what still needs to be tested. Once the fix is ready for testing, create a draft PR. Please ensure the PR description has the test scenarios and test cases listed with checkmarks, so that others can know what still needs to be tested. +- Once all the testing is completed, please update the status of the PR from draft and leave a message. + +:::note +There is nothing stopping you from opening a ticket and working on it yourself, but please be aware that all +bugfixes should be discussed as the approach may have unintended side effects. +::: ::: +::: + +:::warning +Any PRs opened without a corresponding ticket may be rejected. +::: ::: +::: diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/setting-up-a-dev-environment.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/setting-up-a-dev-environment.mdx new file mode 100644 index 00000000000..1133e275dec --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/setting-up-a-dev-environment.mdx @@ -0,0 +1,30 @@ +--- +sidebar_position: 10 +--- + +# 设置开发环境 + +You can set up a development environment by doing the following: + +- Install the latest versions of Go and Git +- `git clone https://github.com/wailsapp/wails` +- `cd wails/v2/cmd/wails` +- `go install` + +NOTE: The directory that you cloned the project into will now be called "clonedir". + +The Wails CLI will now be at the very latest version. + +To update projects to use the latest version, update the project's `go.mod` and ensure the following line is at the bottom of the file: + +`replace github.com/wailsapp/wails/v2 => ` + +Example: + +On Windows: `replace github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2` + +On 'nix: `replace github.com/wailsapp/wails/v2 => /home/me/projects/wails/v2` + +To revert back to a stable version, run: + +`go install github.com/wailsapp/wails/v2/cmd/wails@latest` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/ways-of-contributing.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/ways-of-contributing.mdx new file mode 100644 index 00000000000..3bbe9a889a0 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/contributing/ways-of-contributing.mdx @@ -0,0 +1,18 @@ +--- +sidebar_position: 1 +--- + +# 贡献方式 + +Wails is an open source, community driven project. We welcome anyone to join us in contributing to the project. This documentation is aimed at anyone wishing to get familiar with the project and the development processes. We welcome anyone to join us in contributing to the project. This documentation is aimed at anyone wishing to get familiar with the project and the development processes. + +There are many ways to contribute to the project: + +- Developing new features +- Fixing bugs +- Testing +- Documenting features +- Writing tutorials / guides +- Helping others on the issues + discussions boards + +Guides for these have been created in their own sections. Guides for these have been created in their own sections. Guides for these have been created in their own sections. Before getting started, please introduce yourself in the [Contributing to Wails](https://github.com/wailsapp/wails/discussions/1520) discussion. diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/_category_.json b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/_category_.json new file mode 100644 index 00000000000..597b920dff9 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Getting Started", + "position": 10 +} diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx new file mode 100644 index 00000000000..c4fe879bc4c --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/building.mdx @@ -0,0 +1,22 @@ +--- +sidebar_position: 6 +--- + +# 编译您的项目 + +从项目目录,运行 `wails build`。 这将编译您的项目并将构建的可用于生产的二进制文件保存在 `build/bin` 目录中。 + +如果您运行二进制文件,您应该会看到默认应用程序: + +```mdx-code-block +
+ +
+
+``` + +有关编译选项的更多详细信息,请参阅 [构建命令](../reference/cli#构建)。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx new file mode 100644 index 00000000000..a9020bc38d6 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/development.mdx @@ -0,0 +1,16 @@ +--- +sidebar_position: 5 +--- + +# 开发您的应用程序 + +您可以通过从项目目录运行 `wails dev` 在开发模式下运行您的应用程序。 这将执行以下操作: + +- 构建您的应用程序并运行它 +- 将您的 Go 代码绑定到前端,以便可以从 JavaScript 调用它 +- 使用 [Vite](https://vitejs.dev/) 的强大功能,将监视您的 Go 文件中的修改并在更改时重新构建/重新运行 +- 启动一个 [网络服务器](http://localhost:34115) 通过浏览器为您的应用程序提供服务。 这使您可以使用自己喜欢的浏览器扩展。 你甚至可以从控制台调用你的 Go 代码。 + +首先,在项目目录中运行 `wails dev`。 可以在 [此处](../reference/cli#开发) 找到有关这方面的更多信息。 + +即将提供:教程 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx new file mode 100644 index 00000000000..e6fddf1c5e6 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/firstproject.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 2 +--- + +# 创建项目 + +## 项目生成 + +现在 CLI 已安装,您可以使用 `wails init` 命令生成一个新项目。 + +选择您最喜欢的框架: + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + 使用 JavaScript 生成一个 Svelte 项目:

+ + wails init -n myproject -t svelte + +如果您更愿意使用 TypeScript:
+ + wails init -n myproject -t svelte-ts + +
+ + 使用 JavaScript 生成一个 React 项目:

+ + wails init -n myproject -t react + +如果您更愿意使用 TypeScript:
+ + wails init -n myproject -t react-ts + +
+ + 使用 JavaScript 生成一个 Vue 项目:

+ + wails init -n myproject -t vue + +如果您更愿意使用 TypeScript:
+ + wails init -n myproject -t vue-ts + +
+ + 使用 JavaScript 生成一个 Preact 项目:

+ + wails init -n myproject -t preact + +如果您更愿意使用 TypeScript:
+ + wails init -n myproject -t preact-ts + +
+ + 使用 JavaScript 生成一个 Lit 项目:

+ + wails init -n myproject -t lit + +如果您更愿意使用 TypeScript:
+ + wails init -n myproject -t lit-ts + +
+ + 使用 JavaScript 生成一个 Vanilla 项目:

+ + wails init -n myproject -t vanilla + +如果您更愿意使用 TypeScript:
+ + wails init -n myproject -t vanilla-ts + +
+
+``` + +
+ +还有提供不同功能和框架的 [社区模板](../community/templates.mdx)。 + +要查看其他可用选项,您可以运行 `wails init -help`。 更多详细信息可以在 [初始化命令](../reference/cli#初始化) 中找到。 + +## 项目布局 + +Wails 项目有以下布局: + +``` +. +├── build/ +│ ├── appicon.png +│ ├── darwin/ +│ └── windows/ +├── frontend/ +├── go.mod +├── go.sum +├── main.go +└── wails.json +``` + +### 项目结构概要 + +- `/main.go` - 主应用 +- `/frontend/` - 前端项目文件 +- `/build/` - 项目构建目录 +- `/build/appicon.png` - 应用程序图标 +- `/build/darwin/` - Mac 特定的项目文件 +- `/build/windows/` - Windows 特定的项目文件 +- `/wails.json` - 项目配置 +- `/go.mod` - Go module 文件 +- `/go.sum` - Go module 校验文件 + +`frontend` 目录没有特定于 Wails 的内容,可以是您选择的任何前端项目。 + +`build` 目录在构建过程中使用。 这些文件可以修改以自定义您的构建。 如果从 build 目录中删除文件,将重新生成默认版本。 + +`go.mod` 中的默认模块名称是“changeme”。 您应该将其更改为更合适的内容。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx new file mode 100644 index 00000000000..3e8b2e39f0f --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/gettingstarted/installation.mdx @@ -0,0 +1,89 @@ +--- +sidebar_position: 1 +--- + +# 安装 + +## 支持的平台 + +- Windows 10/11 AMD64/ARM64 +- MacOS 10.13+ AMD64 +- MacOS 11.0+ ARM64 +- Linux AMD64/ARM64 + +## 依赖 + +Wails 有许多安装前需要的常见依赖项: + +- Go 1.18+ +- NPM (Node 15+) + +### Go + +从 [Go 下载页面](https://go.dev/dl/) 下载 Go。 + +确保您遵守官方的 [Go 安装说明](https://golang.org/doc/install#install)。 您还需要确保您的 `PATH` 环境变量包含您的 `~/go/bin` 目录路径。 重启终端并执行以下命令检查: + +- 检查 Go 是否安装正确: `go version` +- 检查 "~/go/bin" 是否在您的 PATH 变量中: `echo $PATH | grep go/bin` + +### NPM + +从 [Node 下载页面](https://nodejs.org/en/download/) 下载 NPM。 最好使用最新版本,因为这是我们通常会测试的版本。 + +运行 `npm --version` 进行验证。 + +## 平台特定依赖关系 + +您还需要安装平台特定的依赖项: + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + Wails 要求安装 xcode 命令行工具。 这可以通过运行 xcode-select --install 来完成。 + + + Wails 要求安装 WebView2 运行时。 一些 Windows 安装已经安装了这个。 您可以使用 wails doctor 命令进行检查。 + + + Linux 需要标准的 gcc 构建工具以及 libgtk3libwebkit。 与其为不同的发行版列出大量命令,Wails 可以尝试确定针对您的特定发行版的安装命令。 安装后运行 wails doctor 以显示如何安装依赖项。 如果您的发行版/包管理器不受支持,请参阅 添加Linux发行版指南。 + + +``` + +## 可选依赖 + +- [UPX](https://upx.github.io/) 用于压缩您的应用程序。 +- [NSIS](https://wails.io/docs/guides/windows-installer/) 用于生成 Windows 安装程序。 + +## 安装 Wails + +运行 `go install github.com/wailsapp/wails/v2/cmd/wails@latest` 安装 Wails CLI。 + +注意:如果您遇到了类似于以下内容的错误: + +```shell +....\Go\pkg\mod\github.com\wailsapp\wails\v2@v2.1.0\pkg\templates\templates.go:28:12: pattern all:ides/*: no matching files found +``` +请检查您是否已安装 Go 1.18+ ︰ +```shell +go version +``` + +## 系统检查 + +运行 `wails doctor` 将检查您是否安装了正确的依赖项。 如果没有,它会就缺少的内容提供建议以帮助纠正问题。 + +## `wails` 命令好像不见了? + +如果您的系统报告缺少 `wails` 命令,请确保您已正确遵循 Go 安装指南。 通常,这意味着您的用户 home 目录中的 `go/bin` 目录不在 `PATH` 环境变量中。 通常情况下还需要关闭并重新打开任何已打开的命令提示符,以便安装程序对环境所做的更改反映在命令提示符中。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/_category_.json b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/_category_.json new file mode 100644 index 00000000000..5935dad936c --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Guides", + "position": 50 +} diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx new file mode 100644 index 00000000000..e5061a6eaa8 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/angular.mdx @@ -0,0 +1,14 @@ +# Angular + +虽然 Wails 没有 Angular 模板,但可以将 Angular 与 Wails 一起使用。 + +## 开发模式 + +要让开发模式与 Angular 一起工作,您需要将以下内容添加到您的 `wails.json` 中: + +```json + "frontend:build": "npx ng build", + "frontend:install": "npm install", + "frontend:dev:watcher": "npx ng serve", + "frontend:dev:serverUrl": "http://localhost:4200", +``` \ No newline at end of file diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx new file mode 100644 index 00000000000..27217a9a6f2 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/application-development.mdx @@ -0,0 +1,215 @@ +# 应用开发 + +使用 Wails 开发应用程序没有硬性规定,但有一些基本准则。 + +## 应用程序设置 + +默认模板使用 `main.go` 配置和运行应用程序, 同时`app.go` 用于定义应用程序逻辑. + +`app.go`文件将定义一个结构体,该结构体有 2 个方法作为主应用程序的回调: + +```go title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} +``` + +- 一旦 Wails 分配了它需要的资源,就会调用 startup 方法,它是创建资源、设置事件侦听器以及应用程序在启动时需要的任何其他东西的好地方。 它提供了一个 `context.Context`, 通常保存在一个结构体字段中。 调用 [运行时](../reference/runtime/intro) 需要此`context.Context`。 如果此方法返回错误,则应用程序将终止。 在开发模式下,错误会输出到控制台。 + +- Shutdown 方法将在关闭过程结束时由 Wails 调用。 这是释放内存和执行关闭任务的好地方。 + +`main.go` 文件通常由对`wails.Run()`的单个调用组成,它接受应用程序配置。 模板使用的模式是,在调用 `wails.Run()` 之前, 我们创建并保存一个在 `app.go` 中定义的结构体的实例在名为 `app` 的变量中。 这个配置是我们添加回调的地方: + +```go {3,9,10} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +可以在 [此处](../howdoesitwork#应用程序生命周期回调) 找到有关应用程序生命周期回调的更多信息。 + +## 绑定方法 + +您可能希望从前端调用 Go 方法。 这通常是通过向 `app.go` 中已经定义的结构体中添加公共方法来实现的: + +```go {16-18} title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +在主应用程序中,`Bind` 字段是我们告诉 Wails 想要绑定什么: + +```go {11-13} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +这将绑定 `App` 结构中的所有公共方法(它永远不会绑定 startup 和 shutdown 方法)。 + +### 绑定多个结构体时处理 context + +如果您想为多个结构绑定方法,但希望每个结构都保留对 context 的引用,以便您可以使用运行时函数,一个好的方式是将上下文从 `OnStartup` 方法传递给您的结构实例: + +```go +func main() { + + app := NewApp() + otherStruct := NewOtherStruct() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: func(ctx context.Context){ + app.SetContext(ctx) + otherStruct.SetContext(ctx) + }, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + otherStruct + }, + }) + if err != nil { + log.Fatal(err) + } +} +``` + +可以在 [此处](../howdoesitwork.mdx#method-binding) 找到有关绑定的更多信息。 + +## 应用程序菜单 + +Wails 支持向您的应用程序添加菜单。 这是通过将 [菜单结构体](../reference/menus#菜单结构体) 传递给应用程序配置来完成的。 常见做法是使用一个返回菜单的方法,更常见的是用作生命周期回调的 `App` 结构体上的方法。 + +```go {11} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Menu: app.menu(), + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +## 资产 + +Wails v2 处理资源的方式的伟大之处在于它不需要处理! 您唯一需要给 Wails 的是一个 `embed.FS`。 你如何做到这一点完全取决于你。 您可以像 vanilla 模板一样使用 vanilla html/css/js 文件。 您可能有一些复杂的构建系统,但这并不影响。 + +运行 `wails build` 时,它会检查项目根目录的 `wails.json` 文件。 文件中有 2 个字段会被读取: + +- "frontend:install" +- "frontend:build" + +第一个,如果有给定,将在 `frontend` 目录中执行以安装 node 模块。 第二个,如果有给定,将在 `frontend` 目录中执行以构建前端项目。 + +如果没有给出这两个字段,那么 Wails 不会对前端做任何操作。 它仅仅被用作 `embed.FS`。 + +### 资产处理程序 + +Wails v2 应用程序可以选择在 `options.App` 中定义一个 `http.Handler`,它允许连接到 AssetServer 以动态创建文件或处理 POST/PUT 请求。 GET 请求总是首先由 `assets` FS 处理。 如果 FS 没有找到请求的文件,请求将被转发到 `http.Handler` 服务。 如果指定,除了 GET 以外的任何请求都将由 `AssetsHandler` 直接处理。 也可以仅通过将 `nil` 指定为 `Assets` 选项来使用 `AssetsHandler`。 + +## 内置开发服务器 + +运行 `wails dev` 将启动内置的开发服务器,它将在您的项目目录中启动一个文件监听器。 默认情况下,如果有任何文件更改,wails 会检查它是否是应用程序文件(默认:.go,可使用 `-e` 标志配置)。 如果是,那么它将重新构建您的应用程序并重新启动它。 如果更改的文件在 assetdir 目录中,它会在很短的时间后重新加载。 + +开发服务器使用一种称为“防抖”的技术,这意味着它不会立即重新加载,因为可能会在短时间内更改多个文件。 当触发发生时,它会在发出重新加载之前等待一定的时间。 如果发生另一个触发,它会再次重置为等待时间。 默认情况下,此值为 100ms。 如果此值不适用于您的项目,则可以使用 `-debounce` 标志进行配置。 如果使用,此值将保存到您的项目配置中并成为默认值。 + +## 外部开发服务器 + +一些框架带有自己的实时重新加载服务器,但是它们将无法利用 Wails Go 绑定。 在这种情况下,最好运行一个监听脚本,将项目重新构建到构建目录中,Wails 将监视该目录。 有关示例,请参阅使用 [rollup](https://rollupjs.org/guide/en/) 的默认 svelte 模板。 + +### Create React App + +The process for a Create-React-App project is slightly more complicated. In order to support live frontend reloading the following configuration needs to be added to your `wails.json`: + +```json + "frontend:dev:watcher": "yarn start", + "frontend:dev:serverUrl": "http://localhost:3000", +``` + +The `frontend:dev:watcher` command will start the Create-React-App development server (hosted on port `3000` typically). The `frontend:dev:serverUrl` command then instructs Wails to serve assets from the development server when loading the frontend rather than from the build folder. In addition to the above, the `index.html` needs to be updated with the following: + +```html + + + + + +``` + +This is required as the watcher command that rebuilds the frontend prevents Wails from injecting the required scripts. This circumvents that issue by ensuring the scripts are always injected. With this configuration, `wails dev` can be run which will appropriately build the frontend and backend with hot-reloading enabled. Additionally, when accessing the application from a browser the React developer tools can now be used on a non-minified version of the application for straightforward debugging. Finally, for faster builds, `wails dev -s` can be run to skip the default building of the frontend by Wails as this is an unnecessary step. + +## Go 模块 + +默认的 Wails 模板会生成一个包含模块名称“changeme”的 `go.mod` 文件。 您应该在项目生成后将其更改为更合适的内容。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx new file mode 100644 index 00000000000..fd81a974d04 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/crossplatform-build.mdx @@ -0,0 +1,66 @@ +# Crossplatform build with Github Actions + +To build a Wails project for all the available platforms, you need to create an application build for each operating system. One effective method to achieve this is by utilizing GitHub Actions. + +An action that facilitates building a Wails app is available at: +https://github.com/dAppServer/wails-build-action + +In case the existing action doesn't fulfill your requirements, you can select only the necessary steps from the source: +https://github.com/dAppServer/wails-build-action/blob/main/action.yml + +Below is a comprehensive example that demonstrates building an app upon the creation of a new Git tag and subsequently uploading it to the Actions artifacts: + +```yaml +name: Wails build + +on: + push: + tags: + # Match any new tag + - '*' + +env: + # Necessary for most environments as build failure can occur due to OOM issues + NODE_OPTIONS: "--max-old-space-size=4096" + +jobs: + build: + strategy: + # Failure in one platform build won't impact the others + fail-fast: false + matrix: + build: + - name: 'App' + platform: 'linux/amd64' + os: 'ubuntu-latest' + - name: 'App' + platform: 'windows/amd64' + os: 'windows-latest' + - name: 'App' + platform: 'darwin/universal' + os: 'macos-latest' + + runs-on: ${{ matrix.build.os }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Build wails + uses: dAppServer/wails-build-action@v2.2 + id: build + with: + build-name: ${{ matrix.build.name }} + build-platform: ${{ matrix.build.platform }} + package: false + go-version: '1.20' +``` + +This example offers opportunities for various enhancements, including: + +- Caching dependencies +- Code signing +- Uploading to platforms like S3, Supbase, etc. +- Injecting secrets as environment variables +- Utilizing environment variables as build variables (such as version variable extracted from the current Git tag) diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx new file mode 100644 index 00000000000..e86b651845d --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/custom-protocol-schemes.mdx @@ -0,0 +1,204 @@ +# Custom Protocol Scheme association + +Custom Protocols feature allows you to associate specific custom protocol with your app so that when users open links with this protocol, +your app is launched to handle them. This can be particularly useful to connect your desktop app with your web app. +In this guide, we'll walk through the steps to implement custom protocols in Wails app. + +## Set Up Custom Protocol Schemes Association: + +To set up custom protocol, you need to modify your application's wails.json file. +In "info" section add a "protocols" section specifying the protocols your app should be associated with. + +For example: + +```json +{ + "info": { + "protocols": [ + { + "scheme": "myapp", + "description": "My App Protocol", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------ | +| scheme | Custom Protocol scheme. e.g. myapp | +| description | Windows-only. The description. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open custom protocol with your app, the system will launch your app and call the `OnUrlOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnUrlOpen: func(url string) { println(url) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows Custom Protocol Schemes is supported only with NSIS installer. During installation, the installer will create a +registry entry for your schemes. When you open url with your app, new instance of app is launched and url is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there (note that `%u` is important in Exec). Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=x-scheme-handler/myapp; +``` + +2. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +``` + +3. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with custom protocol scheme. When you open url with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx new file mode 100644 index 00000000000..647348462af --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/dynamic-assets.mdx @@ -0,0 +1,136 @@ +# 动态资产 + +如果你想为你的前端动态加载或生成资产,你可以使用 [AssetsHandler 选项](../reference/options#资产处理程序) 来实现。 AssetsHandler 是一个通用的 `http.Handler`,对于资产服务器上的任何非 GET 请求以及由于找不到文件而无法从捆绑资产提供服务的 GET 请求,都会调用它。 + +通过安装自定义 AssetsHandler,您可以使用自定义资产服务器提供您自己的资产。 + +## 示例 + +在我们的示例项目中,我们将创建一个简单的资产处理程序,它将从磁盘加载文件: + +```go title=main.go {17-36,49} +package main + +import ( + "embed" + "fmt" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "net/http" + "os" + "strings" +) + +//go:embed all:frontend/dist +var assets embed.FS + +type FileLoader struct { + http.Handler +} + +func NewFileLoader() *FileLoader { + return &FileLoader{} +} + +func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) { + var err error + requestedFilename := strings.TrimPrefix(req.URL.Path, "/") + println("Requesting file:", requestedFilename) + fileData, err := os.ReadFile(requestedFilename) + if err != nil { + res.WriteHeader(http.StatusBadRequest) + res.Write([]byte(fmt.Sprintf("Could not load file %s", requestedFilename))) + } + + res.Write(fileData) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "helloworld", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: NewFileLoader(), + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 255}, + OnStartup: app.startup, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +当我们在开发模式使用 `wails dev` 运行应用程序时,我们将看到以下输出: + +``` +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' failed, using AssetHandler +Requesting file: favicon.ico +``` + +如您所见,当默认资产服务器无法提供 `favicon.ico` 文件时,将调用资产处理程序。 + +如果您右键单击主应用程序并选择“检查”以调出开发工具,您可以通过在控制台中输入以下内容来测试此功能: + +``` +let response = await fetch('does-not-exist.txt'); +``` + +这将在 devtools 中产生错误。 我们可以看到错误是我们所期望的,由我们的自定义资产处理程序返回: + +```mdx-code-block +

+ +

+``` + +但是,如果我们请求 `go.mod`,我们将看到以下输出: + +```mdx-code-block +

+ +

+``` + +此技术可用于将图像直接加载到页面中。 如果我们更新了默认的 vanilla 模板并替换了 logo 图像: + +```html + +``` + +和: + +```html + +``` + +然后我们会看到以下内容: + +```mdx-code-block +

+ +

+``` + +:::warning + +以这种方式暴露您的文件系统是一种安全风险。 建议您正确管理对文件系统的访问。 + +::: diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx new file mode 100644 index 00000000000..167955b12d7 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/file-association.mdx @@ -0,0 +1,244 @@ +# File Association + +File association feature allows you to associate specific file types with your app so that when users open those files, +your app is launched to handle them. This can be particularly useful for text editors, image viewers, or any application +that works with specific file formats. In this guide, we'll walk through the steps to implement file association in Wails app. + +## Set Up File Association: + +To set up file association, you need to modify your application's wails.json file. +In "info" section add a "fileAssociations" section specifying the file types your app should be associated with. + +For example: + +```json +{ + "info": { + "fileAssociations": [ + { + "ext": "wails", + "name": "Wails", + "description": "Wails Application File", + "iconName": "wailsFileIcon", + "role": "Editor" + }, + { + "ext": "jpg", + "name": "JPEG", + "description": "Image File", + "iconName": "jpegFileIcon", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | +| ext | The extension (minus the leading period). e.g. png | +| name | The name. e.g. PNG File | +| iconName | The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows | +| description | Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open file (or files) with your app, the system will launch your app and call the `OnFileOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnFileOpen: func(filePaths []string) { println(filestring) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows file association is supported only with NSIS installer. During installation, the installer will create a +registry entry for your file associations. When you open file with your app, new instance of app is launched and file path is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there. Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=application/x-wails;application/x-test +``` + +2. Create mime types file. Example: + +```xml + + + + Wails Application File + + + +``` + +3. Create icons for your file types. SVG icons are recommended. +4. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload mime types to register file associations +update-mime-database /usr/share/mime +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +# update icons +update-icon-caches /usr/share/icons/* +``` + +5. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ./application-wails-mime.xml + dst: /usr/share/mime/packages/application-x-wails.xml +- src: ./application-test-mime.xml + dst: /usr/share/mime/packages/application-x-test.xml +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with specified file types. When you open file with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx new file mode 100644 index 00000000000..50b89b33bd1 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/frameless.mdx @@ -0,0 +1,87 @@ +# 无边框应用 + +Wails 支持无边框应用程序。 这可以通过使用 [应用程序参数选项](../reference/options#应用程序参数选项) 中的 [无边框](../reference/options#无边框) 字段来实现。 + +Wails 为拖动窗口提供了一个简单的解决方案:任何具有 `--wails-draggable:drag` CSS 样式的 HTML 元素都将充当“拖动句柄”。 此属性适用于所有子元素。 如果您需要指示嵌套元素不应拖动,则在该元素上使用“--wails-draggable:no-drag”属性。 + +```html + + + + + + + +
+ + +
+
+ + + + +``` + +对于一些项目,由于动态样式,可能无法使用 CSS 变量。 在这种情况下,您可以使用 `CSSDragProperty` 和 `CSSDragValue` 应用程序选项来定义将用于指示可拖动区域的属性和值: + +```go title=main.go +package main + +import ( + "embed" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "alwaysontop", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Frameless: true, + CSSDragProperty: "widows", + CSSDragValue: "1", + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +```html title=index.html + + + + + + alwaysontop + + +
+ + + +``` + +:::info 全屏 + +如果您允许您的应用程序全屏显示,则此拖动功能将被禁用。 + +::: diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx new file mode 100644 index 00000000000..7c424686348 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/frontend.mdx @@ -0,0 +1,72 @@ +# 前端 + +## 脚本注入 + +当 Wails 为您的 `index.html` 提供服务时,默认情况下,它会将 2 个脚本注入 `` 标签以加载 `/wails/ipc.js` 和 `/wails/runtime.js`。 这些文件分别安装绑定和运行时。 + +下面的代码显示了这些默认注入的位置: + +```html + + + injection example + + + + + + + +
Please enter your name below 👇
+
+ + +
+ + + + +``` + +### 覆盖默认脚本注入 + +为了给开发人员提供更大的灵活性,有一个 meta 标签可用于自定义此行为: + +```html + +``` + +选项如下: + +| 值 | 描述 | +| ------------------- | -------------------------- | +| noautoinjectruntime | 禁用自动注入 `/wails/runtime.js` | +| noautoinjectipc | 禁用自动注入 `/wails/ipc.js` | +| noautoinject | 禁用所有脚本自动注入 | + +可以使用多个选项,前提是它们以逗号分隔。 + +此代码完全有效并且与自动注入版本的操作相同: + +```html + + + injection example + + + + + + +
Please enter your name below 👇
+
+ + +
+ + + + + + +``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx new file mode 100644 index 00000000000..a7642a7c015 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/ides.mdx @@ -0,0 +1,127 @@ +# 集成开发环境 + +Wails 旨在提供出色的开发体验。 为此,我们现在支持生成 IDE 特定配置以提供更顺畅的项目设置。 + +目前,我们支持 [Visual Studio Code](https://code.visualstudio.com/),但我们希望尽快支持其他 IDE,例如 Goland。 + +## Visual Studio Code + +```mdx-code-block +

+ +

+``` + +使用 `-ide vscode` 标志生成项目时,IDE 文件将与其他项目文件一起创建。 这些文件放置在 `.vscode` 目录中,并为调试应用程序提供正确的配置。 + +生成的 2 个文件是 `tasks.json` 和 `launch.json`。 以下是为默认 vanilla 项目生成的文件: + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/myproject.exe" + ] + } + ] +} +``` + +```json title="launch.json" +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Wails: Debug myproject", + "type": "go", + "request": "launch", + "mode": "exec", + "program": "${workspaceFolder}/build/bin/myproject.exe", + "preLaunchTask": "build", + "cwd": "${workspaceFolder}", + "env": {} + } + ] +} +``` + +### 配置安装和构建步骤 + +`tasks.json` 文件对于默认项目很简单,因为不需要 `npm install` 或 `npm run build` 的步骤。 对于具有前端构建步骤的项目,例如 svelte 模板,我们需要编辑 `tasks.json` 以添加安装和构建步骤: + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "npm install", + "type": "npm", + "script": "install", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "npm run build", + "type": "npm", + "script": "build", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/vscode.exe" + ], + "dependsOn": ["npm install", "npm run build"] + } + ] +} +``` + +:::info 功能增强 + +将来,我们希望生成一个 `tasks.json` 自动包含安装和构建步骤的文件。 + +::: diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx new file mode 100644 index 00000000000..f282894e495 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux-distro-support.mdx @@ -0,0 +1,103 @@ +# Linux 发行版支持 + +## 概述 + +Wails 提供 Linux 支持,但为所有可用发行版提供安装说明是一项不可能完成的任务。 相反,Wails 会尝试确定您开发应用程序所需的包是否可以通过系统的包管理器获得。 目前,我们支持以下包管理器: + +- apt +- dnf +- emerge +- eopkg +- nixpkgs +- pacman +- zypper + +## 添加包名 + +在某些情况下,您的发行版使用受支持的包管理器之一,但包名称不同。 例如,您可能使用 Ubuntu 衍生产品,但 gtk 的包名称可能不同。 Wails 尝试通过遍历包名称列表来找到正确的包。 包列表存储在 `v2/internal/system/packagemanager` 目录中的包管理器特定文件中。 在我们的示例中,是 `v2/internal/system/packagemanager/apt.go`。 + +在此文件中,包列表由以下 `Packages()` 方法定义: + +```go +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +假设在我们的 linux 发行版中,`libgtk-3` 以 `lib-gtk3-dev` 的名称打包。 我们可以通过添加以下行来添加对此的支持: + +```go {5} +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + {Name: "lib-gtk3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +## 添加新的包管理器 + +要添加新的包管理器,请执行以下步骤: + +- 在 `v2/internal/system/packagemanager` 中创建一个名为 `.go` 的新文件,其中 `` 是包管理器的名称。 +- 定义一个符合 `pm.go` 中定义的包管理器接口的结构体。 + +```go +type PackageManager interface { + Name() string + Packages() packagemap + PackageInstalled(*Package) (bool, error) + PackageAvailable(*Package) (bool, error) + InstallCommand(*Package) string +} +``` + +- `Name()` 应该返回包管理器的名称 +- `Packages()` 应该返回一个 `packagemap`,它为依赖项提供候选文件名 +- `PackageInstalled()` 如果安装了指定的包,应该返回`true` +- `PackageAvailable()` 如果指定的软件包未安装但可以安装,则应返回`true` +- `InstallCommand()` 应该返回确切的命令来安装指定的包名 + +查看其他包管理器代码以了解其工作原理。 + +:::info 记住 + +如果您添加了对新包管理器的支持,请不要忘记更新此页面! + +::: diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx new file mode 100644 index 00000000000..dfcdc5fb23a --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/linux.mdx @@ -0,0 +1,18 @@ +# Linux + +此页面包含与开发适用于 Linux 的 Wails 应用程序相关的其他指南。 + +## video 标签不能触发 "ended" 事件 + +使用视频标签时,视频播放完毕后不会触发“结束”事件。 这是 WebkitGTK 中的一个错误,但是您可以使用以下解决方法来修复它: + +```js +videoTag.addEventListener("timeupdate", (event) => { + if (event.target.duration - event.target.currentTime < 0.2) { + let ended = new Event("ended"); + event.target.dispatchEvent(ended); + } +}); +``` + +资料来源:[讨论板](https://github.com/wailsapp/wails/issues/1729#issuecomment-1212291275) 上的 [Lyimmi](https://github.com/Lyimmi) diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx new file mode 100644 index 00000000000..a80900fe676 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/local-development.mdx @@ -0,0 +1,55 @@ +# 本地开发 + +## 概述 + +Wails 一直在开发中,新版本会定期“标记”。 这通常发生在 `master` 分支上所有较新的代码都经过测试并确认有效时。 如果您需要尚未发布的错误修复或功能,可以通过以下步骤使用最新的“前沿风险”版本: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails/v2/cmd/wails` +- `go install` + +注意:您将项目克隆到的目录现在将被称为“clonedir”。 + +现在,Wails CLI 将是最新版本。 + +### 更新您的项目 + +要更新项目以使用最新版本的 Wails 库,请更新项目 `go.mod` 并确保以下行位于文件底部: + +`replace github.com/wailsapp/wails/v2 => ` + +示例: + +在 Windows 上:`replace github.com/wailsapp/wails/v2 => C:\Users\leaan\Documents\wails-v2-beta\wails\v2` + +在'nix 上:`replace github.com/wailsapp/wails/v2 => /home/me/projects/wails/v2` + +要恢复到稳定版本,请运行: + +`go install github.com/wailsapp/wails/v2/cmd/wails@latest` + +## 测试一个分支 + +如果要测试一个分支,请按照上面的说明进行操作,但请确保在安装之前切换要测试的分支: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails` +- `git checkout -b branch-to-test --track origin/branch-to-test` +- `cd v2/cmd/wails` +- `go install` + +确保如上所述 [更新您的项目](#更新您的项目)。 + +## 测试 PR + +如果您想测试 PR,请按照上面的说明进行操作,但请确保在安装前获取 PR 并切换分支。 请替换 `[IDofThePR]` 为 github.com 上显示的 PR 的 ID: + +- `git clone https://github.com/wailsapp/wails` +- `cd wails` +- `git fetch -u origin pull/[IDofThePR]/head:test/pr-[IDofThePR]` +- `git checkout test/pr-[IDofThePR]` +- `git reset --hard HEAD` +- `cd v2/cmd/wails` +- `go install` + +确保如上所述 [更新您的项目](#更新您的项目)。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx new file mode 100644 index 00000000000..b57afca88af --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/mac-appstore.mdx @@ -0,0 +1,97 @@ +# Mac 应用商店指南 + +本页面简要概述了如何将您的 Wails 应用程序提交到 Mac 应用商店。 + +## 前提条件 + +- 您需要有一个 Apple 开发者帐户。 请在 [Apple Developer Program](https://developer.apple.com/support/compare-memberships/) 网站上找到更多信息 +- 您需要在开发人员门户上创建证书(Certificates)、标识符(Identifiers)和应用程序。 更多内容请见下文 +- 你的本地机器上需要安装 Xcode 命令行工具 + +#### 创建证书和标识符 + +1. 前往您的 [Apple 开发者帐户](https://developer.apple.com/account/) +2. 在 `证书(Certificates)、标识符(Identifiers)和个人资料(Profiles)` 下,单击 `标识符(Identifiers)` 并注册新的应用程序 ID。 使用格式 (com.example.app) +3. 在同一页面下,单击 `证书(Certificates)`并为 Mac App Store 分发生成新证书(Certificates)。 下载它们并将证书导入本地计算机上的秘钥串。 + +#### 创建应用程序提交 + +1. 前往 [App Store Connect](https://appstoreconnect.apple.com/apps) 网站 +2. 注册一个新应用程序并链接您在上一步中创建的包 ID +3. 根据 Apple 的要求,使用正确的屏幕截图、描述等填充您的应用程序 +4. 创建新版本的应用 + +#### 创建配置文件 +1. 转到 [Apple 开发者资料](https://developer.apple.com/account/resources/profiles/list) 页面 +2. 为 Mac App Store Distribution 添加新的配置文件 +3. 将 Profile Type 设置为 Mac 并为上面创建的应用程序选择 App ID +4. 选择 Mac App Distribution 证书 +5. 命名嵌入式配置文件并下载创建的配置文件。 + +## Mac 应用商店流程 + +#### 启用 Apple 的 App Sandbox + +提交到 Mac 应用商店的应用程序必须在 Apple 的 [App Sandbox](https://developer.apple.com/app-sandboxing/) 下运行。 您必须创建一个 `entitlements.plist` 文件才能使其工作。 建议在此路径 `{PROJECT_DIR}/build/darwin/entitlements.plist` 下创建此文件。 + +**示例授权文件** + +这是来自 [RiftShare](https://github.com/achhabra2/riftshare) 应用程序的示例授权文件。 作为参考,请输入您的应用所需的权限。 有关详细信息,请参阅 [此站点](https://developer.apple.com/documentation/bundleresources/entitlements)。 您需要将团队 ID 和应用程序名称替换为您上面注册的名称。 + +```xml title="entitlements.plist" + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + com.apple.application-identifier + TEAM_ID.APP_NAME + com.apple.developer.team-identifier + TEAM_ID + + +``` + +上面 **添加嵌入式配置文件** 创建的配置文件需要添加到应用程序的根目录中。 它需要命名为 embedded.provisionprofile。 + +#### 构建并签署应用程序包 + +以下是用于构建和签署您的应用程序以提交 Mac 应用商店的示例脚本。 它假定您正在从根项目目录运行脚本。 + +请注意,用于签署应用程序和签署安装程序的证书是不同的。 请确保两者都导入到秘钥串中。 在秘钥串中找到字符串并将它们插入下面。 在下面填充您的证书名称和应用程序名称。 运行以下脚本将在您的应用程序的根目录中生成一个签名的 `app.pkg` 文件。 + +```bash title="macappstore-build.sh" +#!/bin/bash + +APP_CERTIFICATE="3rd Party Mac Developer Application: YOUR NAME (CODE)" +PKG_CERTIFICATE="3rd Party Mac Developer Installer: YOUR NAME (CODE)" +APP_NAME="YourApp" + +wails build -platform darwin/universal -clean + +cp ./embedded.provisionprofile "./build/bin/$APP_NAME.app/Contents" + +codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist ./build/bin/$APP_NAME.app + +productbuild --sign "$PKG_CERTIFICATE" --component ./build/bin/$APP_NAME.app /Applications ./$APP_NAME.pkg +``` + +#### 上传应用程序包 + +您需要上传生成的包文件并将其关联到您的应用程序,然后才能提交以供审核。 + +1. 从 Mac 应用商店下载 [Transporter App](https://apps.apple.com/us/app/transporter/id1450874784) +2. 打开它并使用您的 Apple ID 登录 +3. 单击 + 号并选择您在上一步中生成的 `APP_NAME.pkg` 文件。 上传它 +4. 返回 [App Store Connect](https://appstoreconnect.apple.com/apps) 站点并导航回您的应用程序提交。 选择您准备在 App 商店上提供的版本。 在 `Build` 下选择您通过 Transporter 上传的包。 + +好了! 您现在可以使用该网站提交您的应用程序以供审核。 几个工作日后,如果一切顺利,您应该会在 Mac 应用商店上看到您的应用程序。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx new file mode 100644 index 00000000000..83de0fdfd8f --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/manual-builds.mdx @@ -0,0 +1,95 @@ +# 手动构建 + +Wails CLI 为项目做了很多繁重的工作,但有时需要手动构建项目。 本文档将讨论 CLI 执行的不同操作以及如何以不同方式实现这一点。 + +## 构建过程 + +当使用 `wails build` 或 `wails dev` 时,Wails CLI 会执行一个通用的构建过程: + + - 安装前端依赖 + - 构建前端项目 + - 生成构建资产 + - 编译应用程序 + - [可选]压缩应用程序 + +### 安装前端依赖 + +#### 命令行步骤 + +- 如果给出了 `-s` 标志,则跳过此步骤 +- 检查 `wails.json` 中是否有安装命令 `frontend:install` +- 如果没有,则跳过此步骤 +- 如果有,则检查前端目录中是否存在 `package.json`。 如果不存在,则跳过这一步 +- 从 `package.json` 文件内容生成 MD5 +- 检查 `package.json.md5` 是否存在,如果存在,则将其内容(MD5 sum)与生成的内容进行比较,以查看内容是否已更改。 如果相同,则跳过此步骤 +- 如果 `package.json.md5` 不存在,则使用生成的 MD5 并创建它 +- 如果现在需要构建,或者 `node_modules` 不存在,或者给出了`-f` 标志,则在前端目录中执行安装命令 + +#### 手动步骤 + +这一步可以从命令行或带有 `npm install` 的前端脚本完成. + +### 构建前端项目 + +#### Wails 命令行 + +- 如果给出了 `-s` 标志,则跳过此步骤 +- 检查 `wails.json` 中是否有构建命令 `frontend:build` +- 如果没有,则跳过此步骤 +- 如果有,就在 frontend 目录下执行它 + +#### 手动步骤 + +这一步可以从命令行或带有前端构建脚本 `npm run build` 的脚本或任何前端构建脚本完成。 + +### 生成资产 + +#### Wails 命令行 + +- 如果设置了`-nopackage` 标志,则跳过此阶段 +- 如果 `build/appicon.png` 文件不存在,则创建一个默认文件 +- 对于 Windows,请参阅 [ Windows](#windows) +- 如果 `build/windows/icon.ico` 不存在,它将从 `build/appicon.png` 图像创建它。 + +##### Windows + +- 如果 `build/windows/icon.ico` 不存在,它将从 `build/appicon.png` 创建 256、128、64、48、32 和 16 大小的图标。 这是使用 [winicon](https://github.com/leaanthony/winicon) 完成的。 +- 如果 `build/windows/.manifest` 文件不存在,它会从默认版本创建它。 +- 将应用程序编译为生产版本(如上所述)。 +- 使用 [winres](https://github.com/tc-hib/winres) 将 icon 和 manifest 打包到一个 `.syso` 文件。 + +#### 手动步骤 + +- 使用[winicon](https://github.com/leaanthony/winicon)命令行工具或者其他工具创建`icon.ico` +- 为您的应用程序创建或者更新 `.manifest` 文件 +- 使用 [winres 命令行](https://github.com/tc-hib/go-winres) 生成一个 `.syso` 文件 + +### 编译应用程序 + +#### Wails 命令行 + +- 如果提供了 `-clean` 标志,则删除并重新创建 `build` 目录 +- 对于 `wails dev`,使用以下默认 Go 标志:`-tags dev -gcflags "all=-N -l"` +- 对于 `wails build`,使用以下默认 Go 标志:`-tags desktop,production -ldflags "-w -s"` + - 在 Windows 上,是 `-ldflags "-w -h -H windowsgui"` +- 传递给 CLI 的附加标签使用 `-tags` 添​​加到默认值中 +- 传递给 CLI 的附加 `ldflags-ldflags` 添加到默认值 +- 传递 `-o` 标志 +- 将使用指定的 Go 编译器 `-compiler` 进行编译 + +#### 手动步骤 + +- 对于 dev 构建,最少的命令是:`go build -tags dev -gcflags "all=-N -l"` +- 对于生产构建,最少的命令是:`go build -tags desktop,production -ldflags "-w -s -H windowsgui"` +- 确保在与 `.syso` 文件相同的目录中进行编译 + +### 压缩应用程序 + +#### Wails 命令行 + +- 如果 `-upx` 已给出标志,将运行 `upx` 程序以使用默认设置压缩应用程序 +- 如果也传递了 `-upxflags` 标志,则使用这些标志而不是默认 + +#### 手动步骤 + +- 手动运行 `upx [flags]` 以压缩应用程序。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx new file mode 100644 index 00000000000..9699ccc63db --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/migrating.mdx @@ -0,0 +1,193 @@ +# 从 v1 迁移 + +## 概述 + +Wails v2 与 v1 相比有重大变化。 本文档旨在重点介绍迁移现有项目的更改和步骤。 + +### 创建应用程序 + +在 v1 中,使用 `wails.CreateApp` 来创建主应用程序,使用 `app.Bind` 来添加绑定,然后使用 `app.Run()` 运行应用程序。 + +示例: + +```go title="v1" + app := wails.CreateApp(&wails.AppConfig{ + Title: "MyApp", + Width: 1024, + Height: 768, + JS: js, + CSS: css, + Colour: "#131313", + }) + app.Bind(basic) + app.Run() +``` + +在 v2 中,只有一个 `wails.Run()` 方法接受 [应用程序参数选项](../reference/options#应用程序参数选项)。 + +```go title="v2" + err := wails.Run(&options.App{ + Title: "MyApp", + Width: 800, + Height: 600, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + basic, + }, + }) +``` + +### 绑定 + +在 v1 中,可以绑定任意函数和结构。 在 v2 中,这已被简化为仅绑定结构体。 以前 v1 传递给 `Bind()` 中的方法的结构实例现在在 [应用程序参数选项 ](../reference/options#应用程序参数选项)`Bind` 字段中指定: + +```go title="v1" + app := wails.CreateApp(/* options */) + app.Bind(basic) +``` + +```go title="v2" + err := wails.Run(&options.App{ + /* other options */ + Bind: []interface{}{ + basic, + }, + }) +``` + +在 v1 中,绑定方法可用于前端的 `window.backend`。 这已更改为 `window.go`。 + +### 应用程序生命周期 + +在 v1 中,绑定结构中有 2 个特殊方法:`WailsInit()` 和 `WailsShutdown()`。 作为应用程序选项的一部分,这些已被 3 个生命周期钩子替换: + +- [应用启动回调](../reference/options.mdx#onstartup) +- [应用退出回调](../reference/options.mdx#onshutdown) +- [前端 Dom 加载完成回调](../reference/options.mdx#ondomready) + +注意:[ 前端 Dom 加载完成回调](../reference/options#前端-dom-加载完成回调)替换了 v1 中的 `wails:ready` 系统事件。 + +这些方法可以是标准函数,但通常的做法是让它们成为结构的一部分: + +```go title="v2" + basic := NewBasicApp() + err := wails.Run(&options.App{ + /* Other Options */ + OnStartup: basic.startup, + OnShutdown: basic.shutdown, + OnDomReady: basic.domready, + }) +... +type Basic struct { + ctx context.Context +} +func (b *Basic) startup(ctx context.Context) { + b.ctx = ctx +} +... +``` + +### 运行时 + +v2 中的运行时比 v1 丰富得多,支持菜单、窗口操作和更好的对话框。 方法的签名略有变化 - 请参阅 [运行时](../reference/runtime/intro)。 + +在 v1 中,[运行时](../reference/runtime/intro) 可通过传递给 `WailsInit()`。 在 v2 中,运行时已移出到它自己的包。 运行时中的每个方法都采用 `context.Context` 传递给了 [应用启动回调](../reference/options#应用启动回调)方法。 + +```go title="Runtime Example" +package main + +import "github.com/wailsapp/wails/v2/pkg/runtime" + +type Basic struct { + ctx context.Context +} + +// startup is called at application startup +func (a *App) startup(ctx context.Context) { + a.ctx = ctx + runtime.LogInfo(ctx, "Application Startup called!") +} +} +} + +``` + +### 资产 + +在 v2 最大的变化是资源的处理方式。 + +在 v1 中,资源通过 2 个应用程序参数选项传递: + +- `JS` - 应用程序的 JavaScript +- `CSS` - 应用程序的 CSS + +这意味着生成单个 JS 和 CSS 文件的责任在于开发人员。 这本质上需要使用繁琐的打包程序,例如 webpack。 + +在 v2 中,Wails 不对您的前端资源做任何预设,就像网络服务器一样。 您的所有应用程序资源都作为 `embed.FS`。 + +**这意味着不需要捆绑您的资产、将图像编码为 Base64 或尝试使用捆绑器配置的黑暗艺术来使用自定义字体**。 + +在启动时,Wails 将扫描给定的`embed.FS`的`index.html`并将其位置用作所有其他应用程序资源的根路径 - 就像网络服务器一样。 + +示例:应用程序具有以下项目布局。 所有最终资源都放在 `frontend/dist`目录中: + +```shell +. +├── build/ +├── frontend/ +│ └── dist/ +│ ├── index.html +│ ├── main.js +│ ├── main.css +│ └── logo.svg +├── main.go +└── wails.json +``` + +应用程序可以通过简单地创建一个 `embed.FS` 来使用这些资源: + +```go title="Assets Example" +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + err := wails.Run(&options.App{ + /* Other Options */ + AssetServer: &assetserver.Options{ + Assets: assets, + }, + }) +} +``` + +当然,如果您愿意,也可以使用打包工具。 唯一的要求是在 Wails 中使用 `embed.FS` 将最终的程序资源目录传递给 [应用程序参数选项](../reference/options#应用程序参数选项) 的 `Assets` 键。 + +### 项目配置 + +在 v1 中,项目配置存储在项目根的 `project.json` 文件中。 在 v2 中,项目配置存储在项目根部的 `wails.json` 文件中。 + +文件的格式略有不同。 下面是区别: + +

+ +| v1 | v2 | 记录 | +| ------------------ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | name | | +| description | | 移除 | +| author / name | author / name | | +| author / email | author / email | | +| version | version | | +| binaryname | outputfilename | 变更 | +| frontend / dir | | 移除 | +| frontend / install | frontend:install | 变更 | +| frontend / build | frontend:build | 变更 | +| frontend / bridge | | 移除 | +| frontend / serve | | 移除 | +| tags | | 移除 | +| | wailsjsdir | 生成 wailsjs 模块的目录 | +| | assetdir | 为开发模式编译的前端资产的目录。 这通常是推断的,可以留空。 | +| | reloaddirs | 以逗号分隔的附加目录列表,用于监视更改并在开发模式下触发重新加载。 只有一些更高级的资产配置才需要这样做。 | + +

diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx new file mode 100644 index 00000000000..13e54ec4678 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/mouse-buttons.mdx @@ -0,0 +1,25 @@ +# 鼠标按钮 + +Wails 运行时拦截鼠标单击以确定无框窗口是否需要调整大小或需要移动窗口。 有人询问如何检测鼠标点击何时发生,因为 `window.onclick` 没有正确报告鼠标按钮。 下面的代码展示了如何检测鼠标点击: + +```javascript +window.addEventListener("mousedown", handleMouseButtonDown); + +function handleMouseButtonDown(event) { + if (event.button === 0) { + // left mouse button + } else if (event.button === 1) { + // middle mouse button + } else if (event.button === 2) { + // right mouse button + } else if (event.button === 3) { + // back mouse button + } else if (event.button === 4) { + // forward mouse button + } else { + // other mouse button + } +} +``` + +参考:https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx new file mode 100644 index 00000000000..c37150a4078 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/obfuscated.mdx @@ -0,0 +1,40 @@ +# 混淆构建 + +Wails 支持使用 [garble](https://github.com/burrowers/garble) 来混淆您的应用程序。 + +要生成混淆构建,您可以将 `-obfuscate` 标志与 `wails build` 命令一起使用: + +```bash +wails build -obfuscated +``` + +要自定义混淆设置,您可以使用以下 `-garbleargs` 标志: + +```bash +wails build -obfuscated -garbleargs "-literals -tiny -seed=myrandomseed" +``` + +这些设置可能会保留在您的 [项目配置](../reference/project-config) 中。 + +## 工作原理 + +在标准构建中,所有绑定的方法都在前端的 `window.go` 变量下可用。 调用这些方法时,会使用完全限定的函数名调用相应的后端方法。 使用混淆构建时,使用 ID 而不是绑定方法的名称。 目录中生成的绑定 `wailsjs` 使用这些 ID 调用后端函数。 + +:::note + +为确保您的应用程序在混淆模式下工作,您必须使用 `wailsjs` 应用程序目录下生成的绑定。 + +::: + +## 示例 + +从绑定中导入“Greet” 方法,如下所示: + +```js +import { Greet } from "../../wailsjs/go/main/App"; + +// snip +Greet("World"); +``` + +将确保该方法在混淆模式下正常工作,因为绑定将使用 ID 重新生成并更新调用机制。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx new file mode 100644 index 00000000000..64673dafd7d --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/overscroll.mdx @@ -0,0 +1,10 @@ +# 滚动超出 + +[Overscroll](https://developer.mozilla.org/zh-CN/docs/Web/CSS/overscroll-behavior) 是当您滚动超出页面内容边界时有时会获得的“弹跳效果”。 这在移动应用程序中很常见。 这可以使用 CSS 禁用: + +```css +html { + height: 100%; + overflow: hidden; +} +``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx new file mode 100644 index 00000000000..33704c645bc --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/routing.mdx @@ -0,0 +1,47 @@ +# 路由 + +路由是一种在应用程序中切换视图的流行方式。 此页面提供了有关如何执行此操作的一些指导。 + +## Vue + +在 Vue 中推荐的路由方法是 [Hash 模式](https://next.router.vuejs.org/guide/essentials/history-mode.html#hash-mode): + +```js +import { createRouter, createWebHashHistory } from "vue-router"; + +const router = createRouter({ + history: createWebHashHistory(), + routes: [ + //... + ], +}); +``` + +## Angular + +在 Angular 中推荐的路由方法是 [HashLocationStrategy](https://codecraft.tv/courses/angular/routing/routing-strategies/#_hashlocationstrategy): + +```ts +RouterModule.forRoot(routes, { useHash: true }); +``` + +## React + +在 React 中推荐的路由方法是 [HashRouter](https://reactrouter.com/en/main/router-components/hash-router): + +```jsx +import { HashRouter } from "react-router-dom"; + +ReactDOM.render( + + {/* The rest of your app goes here */} + + } exact /> + } /> + } /> + {/* more... */} + + , + root +); +``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx new file mode 100644 index 00000000000..7ce7dc9b2fa --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/signing.mdx @@ -0,0 +1,387 @@ +# 代码签名 + +这是有关如何在 MacOS 和 Windows 上对使用 Wails 生成的二进制文件进行签名的指南。 该指南将针对 CI 环境,更具体地说是 GitHub Actions。 + +## Windows + +首先,您需要一个代码签名证书。 如果您还没有,Microsoft 的信息页面会 [在此处](https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/get-a-code-signing-certificate) 列出一些提供商。 请注意,除非您需要编写内核级软件,例如设备驱动程序,否则不需要 EV 证书。 为了签署你的 Wails 应用程序,一个标准的代码签名证书就可以了。 + +在针对自动构建系统之前,与您的证书提供商核实如何在您的本地计算机上签署您的二进制文件可能是一个好主意,这样您就知道是否有任何特殊要求。 例如,[这里](https://www.ssl.com/how-to/using-your-code-signing-certificate/) 是 SSL.com 的 Windows 代码签名指南。 如果您知道如何在本地签名,则可以更轻松地解决 CI 环境中的任何潜在问题。 例如,SSL.com 代码签名证书需要 [SignTool.exe](https://docs.microsoft.com/en-us/windows/win32/seccrypto/signtool) 的 `/tr` 标志, 而其他提供商可能只需要 `/tr` 标志来提供时间戳服务器。 用于签署 [此类](https://github.com/Dana-Prajea/code-sign-action) Windows 二进制文件的流行 GitHub Actions 不支持 SignTool.exe 上的 `/tr` 标志。 因此,本指南将重点介绍使用 PowerShell 命令手动签署我们的应用程序,但如果您愿意,可以使用类似 [代码签名操作](https://github.com/Dana-Prajea/code-sign-action) 的操作。 + +首先,让我们确保我们能够在我们的 GitHub CI 中构建我们的 Wails 应用程序。 这是一个小型工作流模板: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend manually here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +接下来,我们需要让 GitHub 工作流访问我们的签名证书。 这是通过将您的 .pfx 或 .p12 证书编码为 base64 字符串来完成的。 要在 PowerShell 中执行此操作,您可以使用以下命令,假设您的证书名为“my-cert.p12”: + +```PowerShell +certutil -encode .\my-cert.p12 my-cert-base64.txt +``` + +您现在应该拥有带有 base64 编码证书的 .txt 文件。 它应该以 _-----BEGIN CERTIFICATE-----_ 开头并以 _-----END CERTIFICATE-----_ 结尾。 现在你需要在 GitHub 上创建两个 action secret。 导航到 _Settings -> Secrets -> Actions_ 并创建以下两个 secrets: + +- **WIN_SIGNING_CERT** 您的 base64 编码证书文本的内容。 +- **WIN_SIGNING_CERT_PASSWORD** 您的证书密码的内容。 + +现在我们准备好使用以下两种方法之一在我们的工作流程中实现签名: + +### 方法一:使用命令签名 + +此方法使用 PowerShell 命令对我们的应用程序进行签名,并让您控制整个签名过程。 + +在该 `"Build Wails app"` 步骤之后,我们可以将以下步骤添加到我们的工作流程中: + +```yaml +- name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd /t /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' + +``` + +此脚本为您的证书文件创建一个新目录,从我们的 base64 密钥创建证书文件,将其转换为 .pfx 文件,最后对二进制文件进行签名。 最后一行需要替换以下变量: + +- **签名算法**:通常是 sha256。 +- **时间戳服务器**:与您的证书一起使用的时间戳服务器的 URL。 +- **二进制路径**:要签名的二进制文件的路径。 + +鉴于我们的 Wails 配置将 `outputfilename` 设置为“app.exe”并且我们拥有来自 SSL.com 的证书,这将是我们的工作流程: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\app.exe + + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +### 方法二:Action自动签名 + +可以使用像 [这样](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate) 的 Windows 代码签名操作,但请注意,它需要证书的 SHA1 哈希和证书名称。 查看如何在 Action 的 [市场](https://github.com/marketplace/actions/code-sign-a-file-with-pfx-certificate) 上配置它的示例。 + +--- + +## MacOS + +首先,您需要 Apple 提供的代码签名证书。 如果您没有,简单的谷歌搜索将帮助您获得一个。 获得证书后,您需要将其导出并将其编码为 base64。 本 [教程](https://localazy.com/blog/how-to-automatically-sign-macos-apps-using-github-actions) 向您展示了如何以简单的方式做到这一点。 导出 .p12 证书文件后,您可以使用以下命令将其编码为 base64,如教程中所示: + +```bash +base64 Certificates.p12 | pbcopy +``` + +现在您已准备好创建一些 GitHub 项目 secrets,就像在 Windows 中一样: + +- **APPLE_DEVELOPER_CERTIFICATE_P12_BASE64** 您新复制的 base64 证书的内容。 +- **APPLE_DEVELOPER_CERTIFICATE_PASSWORD** 与您的证书密码的内容。 +- **APPLE_PASSWORD** 包含您可以在 [此处](https://appleid.apple.com/account/manage) 生成的 Apple-ID 帐户的应用程序特定密码的内容。 + +让我们确保我们能够在我们的 GitHub Action 工作流程中构建我们的 Wails 应用程序。 这是一个小模板: + +```yaml +name: "example" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +对于 macOS 上的代码签名,[gon](https://github.com/mitchellh/gon) 是一个非常方便的工具,用于代码签名和与 Apple 服务器通信,也是用 Go 编写的,将在本指南中使用。 + +在 `Build Wails 应用` 步骤之后,将以下内容添加到工作流中: + +```yaml +- name: MacOS download gon for code signing and app notarization + if: matrix.platform == 'macos-latest' + run: | + brew install mitchellh/gon/gon +``` + +Now we need to configure some gon config files in our `build/darwin` directory: + +1. gon-sign.json: + +```json +{ + "source": ["./build/bin/app.app"], + "bundle_id": "app.myapp", + "apple_id": { + "username": "my-appleid@email.com", + "password": "@env:APPLE_PASSWORD" + }, + "sign": { + "application_identity": "Developer ID Application: My Name" + } +} +``` + +其中 `source` 是您的 Wails 二进制文件,`bundle_id` 是您的捆绑包 ID,`apple_id` 包含您之前创建的 Apple ID 用户名和 App-Specific 密码,`sign.application_identity` 是您的身份,您可以通过运行以下命令找到它: + +```bash +security find-identity -v -p codesigning +``` + +2. entitlements.plist: + +```plist + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.files.downloads.read-write + + + +``` + +在此文件中,您可以配置应用所需的权利,例如 如果您的应用使用相机,相机权限。 在 [此处](https://developer.apple.com/documentation/bundleresources/entitlements) 阅读有关权利的更多信息。 + +确保您已使用您在 `gon-sign.json` 中输入的相同包 ID 更新了 `Info.plist` 文件。 这是一个示例 `Info.plist` 文件: + +```plist + + + CFBundlePackageTypeAPPL + CFBundleNameMyApp + CFBundleExecutableapp + CFBundleIdentifierapp.myapp + CFBundleVersion0.1.0 + CFBundleGetInfoStringMy app is cool and nice and chill and + CFBundleShortVersionString0.1.0 + CFBundleIconFileiconfile + LSMinimumSystemVersion10.13.0 + NSHighResolutionCapabletrue + LSApplicationCategoryTypepublic.app-category.utilities + NSHumanReadableCopyright© Me + +``` + +现在我们准备好在构建 Wails 应用程序后在我们的工作流程中添加签名步骤: + +```yaml +- name: Import Code-Signing Certificates for macOS + if: matrix.platform == 'macos-latest' + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} +- name: Sign our macOS binary + if: matrix.platform == 'macos-latest' + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json +``` + +请注意,与 Apple 签署二进制文件可能需要几分钟到几小时。 + +## 组合工作流文件: + +这是我们结合了 Windows + macOS 的 GitHub 工作流文件: + +```yaml +name: "example combined" +on: + workflow_dispatch: + # This Action only starts when you go to Actions and manually run the workflow. + +jobs: + package: + strategy: + matrix: + platform: [windows-latest, macos-latest] + go-version: [1.18] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: setup node + uses: actions/setup-node@v2 + with: + node-version: 14 + # You may need to manually build you frontend here, unless you have configured frontend build and install commands in wails.json. + - name: Get Wails + run: go install github.com/wailsapp/wails/v2/cmd/wails@latest + - name: Build Wails app + run: | + wails build + - name: MacOS download gon for code signing and app notarization + if: matrix.platform == 'macos-latest' + run: | + brew install mitchellh/gon/gon + - name: Import Code-Signing Certificates for macOS + if: matrix.platform == 'macos-latest' + uses: Apple-Actions/import-codesign-certs@v1 + with: + # The certificates in a PKCS12 file encoded as a base64 string + p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }} + # The password used to import the PKCS12 file. + p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }} + - name: Sign our macOS binary + if: matrix.platform == 'macos-latest' + run: | + echo "Signing Package" + gon -log-level=info ./build/darwin/gon-sign.json + - name: Sign Windows binaries + if: matrix.platform == 'windows-latest' + run: | + echo "Creating certificate file" + New-Item -ItemType directory -Path certificate + Set-Content -Path certificate\certificate.txt -Value '${{ secrets.WIN_SIGNING_CERT }}' + certutil -decode certificate\certificate.txt certificate\certificate.pfx + echo "Signing our binaries" + & 'C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe' sign /fd sha256 /tr http://ts.ssl.com /f certificate\certificate.pfx /p '${{ secrets.WIN_SIGNING_CERT_PASSWORD }}' .\build\bin\Monitor.exe + - name: upload artifacts macOS + if: matrix.platform == 'macos-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-macos + path: build/bin/* + - name: upload artifacts windows + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v2 + with: + name: wails-binaries-windows + path: build/bin/* +``` + +# 尾注 + +本指南受 RiftShare 项目及其工作流程的启发,强烈建议在 [此处](https://github.com/achhabra2/riftshare/blob/main/.github/workflows/build.yaml) 查看。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx new file mode 100644 index 00000000000..dc7706f8ffa --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/single-instance-lock.mdx @@ -0,0 +1,81 @@ +# Single Instance Lock + +Single instance lock is a mechanism that allows you to prevent multiple instances of your app from running at the same time. +It is useful for apps that are designed to open files from the command line or from the OS file explorer. + +## Important + +Single Instance Lock does not implement a secure communications protocol between instances. When using single instance lock, +your app should treat any data passed to it from second instance callback as untrusted. +You should verify that args that you receive are valid and don't contain any malicious data. + +## How it works + +Windows: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via a shared window using [SendMessage](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage) +macOS: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via [NSDistributedNotificationCenter](https://developer.apple.com/documentation/foundation/nsdistributednotificationcenter) +Linux: Single instance lock is implemented using [dbus](https://www.freedesktop.org/wiki/Software/dbus/). The dbus name is generated from the unique id that you provide. Data is passed to the first instance via [dbus](https://www.freedesktop.org/wiki/Software/dbus/) + +## Usage + +When creating your app, you can enable single instance lock by passing a `SingleInstanceLock` struct to the `App` struct. +Use the `UniqueId` field to specify a unique id for your app. +This id is used to generate the mutex name on Windows and macOS and the dbus name on Linux. Use a UUID to ensure that the id is unique. +The `OnSecondInstanceLaunch` field is used to specify a callback that is called when a second instance of your app is launched. +The callback receives a `SecondInstanceData` struct that contains the command line arguments passed to the second instance and the working directory of the second instance. + +Note that OnSecondInstanceLaunch don't trigger windows focus. +You need to call `runtime.WindowUnminimise` and `runtime.Show` to bring your app to the front. +Note that on linux systems window managers may prevent your app from being brought to the front to avoid stealing focus. + +```go title="main.go" +var wailsContext *context.Context + +// NewApp creates a new App application struct +func NewApp() *App { + return &App{} +} + +// startup is called when the app starts. The context is saved +// so we can call the runtime methods +func (a *App) startup(ctx context.Context) { + wailsContext = &ctx +} + +func (a *App) onSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) { + secondInstanceArgs = secondInstanceData.Args + + println("user opened second instance", strings.Join(secondInstanceData.Args, ",")) + println("user opened second from", secondInstanceData.WorkingDirectory) + runtime.WindowUnminimise(*wailsContext) + runtime.Show(*wailsContext) + go runtime.EventsEmit(*wailsContext, "launchArgs", secondInstanceArgs) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + OnStartup: app.startup, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx new file mode 100644 index 00000000000..4651c422ed1 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/sveltekit.mdx @@ -0,0 +1,153 @@ +# SvelteKit + +This guide will go into: + +1. Miminal Installation Steps - The steps needed to get a minimum Wails setup working for SvelteKit. +2. Install Script - Bash script for accomplishing the Minimal Installation Steps with optional Wails branding. +3. Important Notes - Issues that can be encountered when using SvelteKit + Wails and fixes. + +## 1. Minimal Installation Steps + +##### Install Wails for Svelte. + +- `wails init -n myapp -t svelte` + +##### Delete the svelte frontend. + +- Navigate into your newly created myapp folder. +- Delete the folder named "frontend" + +##### While in the Wails project root. Use your favorite package manager and install SvelteKit as the new frontend. Follow the prompts. + +- `npm create svelte@latest frontend` + +##### Modify wails.json. + +- Add `"wailsjsdir": "./frontend/src/lib",` Do note that this is where your Go and runtime functions will appear. +- Change your package manager frontend here if not using npm. + +##### Modify main.go. + +- The first comment `//go:embed all:frontend/dist` needs to be changed to `//go:embed all:frontend/build` + +##### Install/remove dependencies using your favorite package manager. + +- Navigate into your "frontend" folder. +- `npm i` +- `npm uninstall @sveltejs/adapter-auto` +- `npm i -D @sveltejs/adapter-static` + +##### Change adapter in svelte.config.js + +- First line of file change `import adapter from '@sveltejs/adapter-auto';` to `import adapter from '@sveltejs/adapter-static';` + +##### Put SvelteKit into SPA mode with prerendering. + +- Create a file under myapp/frontend/src/routes/ named +layout.ts/+layout.js. +- Add two lines into the newly created file `export const prerender = true` and `export const ssr = false` + +##### Test installation. + +- Navigate back into the Wails project root (one directory up). +- run `wails dev` +- If the application doesn't run please check through the previous steps. + +## 2. Install Script + +##### This Bash Script does the steps listed above. Make sure to read over the script and understand what the script is doing on your computer. + +- Create a file sveltekit-wails.sh +- Copy the below code into the new file then save it. +- Make it executable with `chmod +x sveltekit-wails.sh` +- Brand is an optional param below that adds back in the wails branding. Leave third param blank to not insert the Wails branding. +- Example usage: `./sveltekit-wails.sh pnpm newapp brand` + +##### sveltekit-wails.sh: + +``` +manager=$1 +project=$2 +brand=$3 +wails init -n $project -t svelte +cd $project +sed -i "s|npm|$manager|g" wails.json +sed -i 's|"auto",|"auto",\n "wailsjsdir": "./frontend/src/lib",|' wails.json +sed -i "s|all:frontend/dist|all:frontend/build|" main.go +if [[ -n $brand ]]; then + mv frontend/src/App.svelte +page.svelte + sed -i "s|'./assets|'\$lib/assets|" +page.svelte + sed -i "s|'../wails|'\$lib/wails|" +page.svelte + mv frontend/src/assets . +fi +rm -r frontend +$manager create svelte@latest frontend +if [[ -n $brand ]]; then + mv +page.svelte frontend/src/routes/+page.svelte + mkdir frontend/src/lib + mv assets frontend/src/lib/ +fi +cd frontend +$manager i +$manager uninstall @sveltejs/adapter-auto +$manager i -D @sveltejs/adapter-static +echo -e "export const prerender = true\nexport const ssr = false" > src/routes/+layout.ts +sed -i "s|-auto';|-static';|" svelte.config.js +cd .. +wails dev +``` + +## 3. Important Notes + +##### Server files will cause build failures. + +- \+layout.server.ts, +page.server.ts, +server.ts or any file with "server" in the name will fail to build as all routes are prerendered. + +##### The Wails runtime unloads with full page navigations! + +- Anything that causes full page navigations: `window.location.href = '//'` or Context menu reload when using wails dev. What this means is that you can end up losing the ability to call any runtime breaking the app. There are two ways to work around this. +- Use `import { goto } from '$app/navigation'` then call `goto('//')` in your +page.svelte. This will prevent a full page navigation. +- If full page navigation can't be prevented the Wails runtime can be added to all pages by adding the below into the `` of myapp/frontend/src/app.html + +``` + +... + + + +... + +``` + +See https://wails.io/docs/guides/frontend for more information. + +##### Inital data can be loaded and refreshed from +page.ts/+page.js to +page.svelte. + +- \+page.ts/+page.js works well with load() https://kit.svelte.dev/docs/load#page-data +- invalidateAll() in +page.svelte will call load() from +page.ts/+page.js https://kit.svelte.dev/docs/load#rerunning-load-functions-manual-invalidation. + +##### Error Handling + +- Expected errors using Throw error works in +page.ts/+page.js with a +error.svelte page. https://kit.svelte.dev/docs/errors#expected-errors +- Unexpected errors will cause the application to become unusable. Only recovery option (known so far) from unexpected errors is to reload the app. To do this create a file myapp/frontend/src/hooks.client.ts then add the below code to the file. + +``` +import { WindowReloadApp } from '$lib/wailsjs/runtime/runtime' +export async function handleError() { + WindowReloadApp() +} +``` + +##### Using Forms and handling functions + +- The simplest way is to call a function from the form is the standard, bind:value your variables and prevent submission `` +- The more advanced way is to use:enhance (progressive enhancement) which will allow for convenient access to formData, formElement, submitter. The important note is to always cancel() the form which prevents server side behavior. https://kit.svelte.dev/docs/form-actions#progressive-enhancement Example: + +``` + { + cancel() + console.log(Object.fromEntries(formData)) + console.log(formElement) + console.log(submitter) + handle() +}}> +``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx new file mode 100644 index 00000000000..7f701203d1c --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/templates.mdx @@ -0,0 +1,97 @@ +# 模板 + +Wails 从预先创建的模板生成项目。 在 v1 中,这是一组难以维护的项目,这些项目可能会过时。 在 v2 中,为了增强社区的能力,为模板添加了一些新功能: + +- 能够从 [远程模板](../reference/cli#远程模板) 生成项目 +- 帮助创建自己的模板的工具 + +## 创建模板 + +要创建模板,您可以使用 `wails generate template` 命令。 要生成默认模板,请运行: + +`wails generate template -name mytemplate` + +这将使用默认文件创建“mytemplate”目录: + +```shell title=mytemplate/ +. +|-- NEXTSTEPS.md +|-- README.md +|-- app.tmpl.go +|-- frontend +| `-- dist +| |-- assets +| | |-- fonts +| | | |-- OFL.txt +| | | `-- nunito-v16-latin-regular.woff2 +| | `-- images +| | `-- logo-dark.svg +| |-- index.html +| |-- main.css +| `-- main.js +|-- go.mod.tmpl +|-- main.tmpl.go +|-- template.json +`-- wails.tmpl.json +``` + +### 模板概述 + +默认模板包含以下文件和目录: + +| 文件名 / 目录 | 描述 | +| --------------- | ----------------- | +| NEXTSTEPS.md | 有关如何完成模板的说明 | +| README.md | 随模板发布的 README | +| app.tmpl.go | `app.go` 模板文件 | +| frontend/ | 包含前端资源的目录 | +| go.mod.tmpl | `go.mod` 模板文件 | +| main.tmpl.go | `main.go` 模板文件 | +| template.json | 模板元数据 | +| wails.tmpl.json | `wails.json` 模板文件 | + +此时,建议按照 `NEXTSTEPS.md` 中的步骤操作。 + +## 从现有项目创建模板 + +通过在生成模板时将路径传递给项目,可以从现有的前端项目创建模板。 我们现在将介绍如何创建 Vue 3 模板: + +- 安装 vue cli: `npm install -g @vue/cli` +- 创建默认项目:`vue create vue3-base` + - 选择 `Default (Vue 3) ([Vue 3] babel, eslint)` +- 项目生成后,运行: + +```shell +> wails generate template -name wails-vue3-template -frontend .\vue3-base\ +Extracting base template files... +Migrating existing project files to frontend directory... +Updating package.json data... +Renaming package.json -> package.tmpl.json... +Updating package-lock.json data... +Renaming package-lock.json -> package-lock.tmpl.json... +``` + +- 现在可以按照 `NEXTSTEPS.md` 中指定的方式定制模板。 +- 一旦文件准备完毕,就可以通过运行命令来测试它:`wails init -n my-vue3-project -t .\wails-vue3-template\` +- 要测试新项目,请运行:`cd my-vue3-project` then `wails build` +- 项目编译完成后,运行它:`.\build\bin\my-vue3-project.exe` +- 您应该有了一个功能齐全的 Vue3 应用程序: + +```mdx-code-block +
+ +
+``` + +## 发布模板 + +发布模板只是将文件推送到 GitHub。 鼓励以下最佳实践: + +- 从前端目录中删除任何不需要的文件和目录(例如:.git) +- 确保 `template.json` 完整,尤其是 `helpurl` +- 将文件推送到 GitHub +- 在 [社区模板](../community/templates) 页面上创建 PR +- 在 [模板公告](https://github.com/wailsapp/wails/discussions/825) 讨论板上发布模板 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx new file mode 100644 index 00000000000..3f12baf7d60 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/troubleshooting.mdx @@ -0,0 +1,368 @@ +# 故障排除 + +各种故障排除技巧。 + +## `wails` 命令好像不见了? + +如果您的系统报告缺少 `wails` 命令,请确保您已正确遵循 Go 安装指南。 通常,这意味着您的用户 home 目录中的 `go/bin` 目录不在 `PATH` 环境变量中。 通常情况下还需要关闭并重新打开任何已打开的命令提示符,以便安装程序对环境所做的更改反映在命令提示符中。 + +## 我的应用程序正在显示白屏/空白屏幕 + +检查您的应用程序是否包含正确目录中的资产。 在您的 `main.go` 文件中,您将拥有类似于以下代码的内容: + +```go +//go:embed all:frontend/dist +var assets embed.FS +``` + +检查它是否 `frontend/dist` 包含您的应用程序资产。 + +### Mac + +如果在 Mac 上发生这种情况,请尝试将以下内容添加到您的 `Info.plist`: + +```xml +NSAppTransportSecurity + + NSAllowsLocalNetworking + + +``` + +参考:https://github.com/wailsapp/wails/issues/1504#issuecomment-1174317433 + +## Mac 应用程序无效 + +如果您构建的应用程序在 finder 中如下所示: + +```mdx-code-block +

+ +

+``` + +您的申请很可能 `info.plist` 是无效的。 更新 `build/.app/Contents/info.plist`文件 并检查数据是否有效,比如:检查二进制名称是否正确。 要保留更改,请将文件复制回 `build/darwin` 目录。 + +## 我的应用程序未在 Windows 资源管理器中显示正确的图标 + +如果您的应用程序未显示正确的图标,请尝试删除位于 `C:\Users\<您的用户名>\AppData\Local` 目录中的隐藏 `IconCache.db` 文件。 这将强制 Windows 重建图标缓存。 + +来源:https://github.com/wailsapp/wails/issues/2360#issuecomment-1556070036 + +## 无法使用可变参数 + +如果您有使用可变参数定义的后端方法,例如: + +```go +func (a *App) TestFunc(msg string, args ...interface{}) error { + // Code +} +``` + +像这样从前端调用此方法将失败: + +```js +var msg = "Hello: "; +var args = ["Go", "JS"]; +window.go.main.App.TestFunc(msg, ...args) + .then((result) => { + //do things here + }) + .catch((error) => { + //handle error + }); +``` + +解决方法: + +```js +var msg = "Hello "; +var args = ["Go", "JS"]; +window.go.main.App.TestFunc(msg, args) + .then((result) => { + //without the 3 dots + //do things here + }) + .catch((error) => { + //handle error + }); +``` + +致谢:https://github.com/wailsapp/wails/issues/1186 + +## 我正在尝试安装Wails时获取代理错误 + +如果您遇到这样的错误: + +``` +"https://proxy.golang.org/github.com/wailsapp/wails/cmd/wails/@v/list": dial tcp 172.217.163.49:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. +``` + +这可能是因为官方 Go Proxy 被阻止(中国用户报告了这一点)。 解决方案是手动设置代理,例如: + +``` +go env -w GO111MODULE=on +go env -w GOPROXY=https://goproxy.cn,direct +``` + +来源:https://github.com/wailsapp/wails/issues/1233 + +## 没有生成正确的 TypeScript 类型 + +有时生成的 TypeScript 没有正确的类型。 `ts_type` 为了缓解这种情况,可以使用 struct 标签指定应该生成哪些类型。 有关详细信息,请阅读 [此](https://github.com/tkrajina/typescriptify-golang-structs#custom-types) 内容。 + +## 当我离开 `index.html`时,我无法在前端调用方法 + +如果您导航 `index.html` 到一个新的 html 文件,上下文将会丢失。 这可以通过将以下导入添加到 `` 您导航到的任何新页面的部分来解决: + +```html + + + + +``` + +来源:https://github.com/wailsapp/wails/discussions/1512 + +## 运行 `wails dev` 出现 `too many open files` 错误 + +默认情况下,macOS 最多只能打开 256 个文件。 这会影响 `wails dev` 命令 可以通过在终端中运行:`ulimit -n 1024` 来增加此限制。 + +FSNotify 正在 [寻求转移到苹果](https://github.com/fsnotify/fsnotify/issues/11)。 如果这不能很快完成,我们将创建自己的实现,在 [此处](https://github.com/wailsapp/wails/issues/1733) 跟踪。 + +## 我的 Mac 应用程序给了我奇怪的编译错误 + +一些用户报告看到编译错误,如下所示: + +```shell +# github.com/wailsapp/wails/v2/internal/frontend/desktop/darwin +In file included from ../../pkg/mod/github.com/wailsapp/wails/v2@v2.0.0-beta.44.2/internal/frontend/desktop/darwin/callbacks.go:9: +In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:12: +/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSBundle.h:91:143: error: function does not return NSString +- (NSAttributedString *)localizedAttributedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName NS_FORMAT_ARGUMENT(1) NS_REFINED_FOR_SWIFT API_AVAILABLE(macos(12.0), ios(15.0), watchos(8.0), tvos(15.0)); + ~~~~~~~~~~~~~~ ^ ~ +/Library/Developer/CommandLineTools/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:103:48: note: expanded from macro 'NS_FORMAT_ARGUMENT' + #define NS_FORMAT_ARGUMENT(A) __attribute__ ((format_arg(A))) +``` + +这 _通常_ 是由于您正在运行的操作系统版本和安装的 XCode 命令行工具的版本不匹配。 如果您看到这样的错误,请尝试将您的 XCode 命令行工具升级到最新版本。 + +如果重新安装 Xcode 命令工具仍然失败,您可以通过以下方式检查工具包所在的路径: + +`xcode-select -p` + +如果显示 `/Applications/Xcode.app/Contents/Developer` ,运行 `sudo xcode-select --twitter /Library/Developer/CommandLineTools` + +来源:https://github.com/wailsapp/wails/issues/1806 和 https://github.com/wailsapp/wails/issues/1140#issuecomment-1290446496 + +## My application won't compile on Mac + +如果您遇到这样的错误: + +```shell +l1@m2 GoEasyDesigner % go build -tags dev -gcflags "all=-N -l" +/Users/l1/sdk/go1.20.5/pkg/tool/darwin_arm64/link: running clang failed: exit status 1 +Undefined symbols for architecture arm64: + "_OBJC_CLASS_$_UTType", referenced from: + objc-class-ref in 000016.o +ld: symbol(s) not found for architecture arm64 +clang: error: linker command failed with exit code 1 (use -v to see invocation) +``` +Ensure you have the latest SDK installed. If so and you're still experiencing this issue, try the following: + +```shell +export CGO_LDFLAGS="-framework UniformTypeIdentifiers" && go build -tags dev -gcflags "all=-N -l" +``` + +Sources: https://github.com/wailsapp/wails/pull/2925#issuecomment-1726828562 + + +-- + +## 无法启动服务:主机版本“x.x.x”与二进制版本“x.x.x”不匹配 + +最好将 `frontend/node_modules` 和 `frontend/package-lock.json` 添加到您的 `.gitignore` 中。 否则,当在另一台可能安装了不同版本 Node 的机器上打开您的存储库时,您可能无法运行您的应用程序。 + +如果发生这种情况,只需删除 `frontend/node_modules` 和 `frontend/package-lock.json` 并再次运行 `wails build` 或 `wails dev` 命令。 + +## 构建过程停留在“生成绑定” + +绑定生成过程在特殊模式下运行应用程序。 如果应用程序有意或无意地包含一个无限循环(即在 `wails.Run()` 结束后不退出),这可能导致构建过程停留在绑定生成阶段。 请确保您的代码正确退出。 + +## Mac application flashes white at startup + +This is due to the default background of the webview being white. If you want to use the window background colour instead, you can make the webview background transparent using the following config: + +```go + err := wails.Run(&options.App{ + Title: "macflash", + Width: 1024, + Height: 768, + // Other settings + Mac: &mac.Options{ + WebviewIsTransparent: true, + }, + }) +``` + +## I get a "Microsoft Edge can't read or write to its data directory" error when running my program as admin on Windows + +You set your program to require admin permissions and it worked great! Unfortunately, some users are seeing a "Microsoft Edge can't read or write to its data directory" error when running it. + +When a Windows machine has two local accounts: + +- Alice, an admin +- Bob, a regular user + +Bob sees a UAC prompt when running your program. Bob enters Alice's admin credentials into this prompt. The app launches with admin permissions under Alice's account. + +Wails instructs WebView2 to store user data at the specified `WebviewUserDataPath`. It defaults to `%APPDATA%\[BinaryName.exe]`. + +Because the application is running under Alice's account, `%APPDATA%\[BinaryName.exe]` resolves to `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`. + +WebView2 [creates some child processes under Bob's logged-in account instead of Alice's admin account](https://github.com/MicrosoftEdge/WebView2Feedback/issues/932#issue-807464179). Since Bob cannot access `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`, the "Microsoft Edge can't read or write to its data directory" error is shown. + +Possible solution #1: + +Refactor your application to work without constant admin permissions. If you just need to perform a small set of admin tasks (such as running an updater), you can run your application with the minimum permissions and then use the `runas` command to run these tasks with admin permissions as needed: + +```go +//go:build windows + +package sample + +import ( + "golang.org/x/sys/windows" + "syscall" +) + +// Calling RunAs("C:\path\to\my\updater.exe") shows Bob a UAC prompt. Bob enters Alice's admin credentials. The updater launches with admin permissions under Alice's account. +func RunAs(path string) error { + verbPtr, _ := syscall.UTF16PtrFromString("runas") + exePtr, _ := syscall.UTF16PtrFromString(path) + cwdPtr, _ := syscall.UTF16PtrFromString("") + argPtr, _ := syscall.UTF16PtrFromString("") + + var showCmd int32 = 1 //SW_NORMAL + + err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd) + if err != nil { + return err + } + return nil +} +``` + +Possible solution #2: + +Run your application with extended permissions. If you absolutely must run with constant admin permissions, WebView2 will function correctly if you use a data directory accessible by both users and you also launch your app with the `SeBackupPrivilege`, `SeDebugPrivilege`, and `SeRestorePrivilege` permissions. Here's an example: + +```go +package main + +import ( + "embed" + "os" + "runtime" + + "github.com/fourcorelabs/wintoken" + "github.com/hectane/go-acl" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +//go:embed all:frontend/dist +var assets embed.FS + +const ( + fixedTokenKey = "SAMPLE_RANDOM_KEY" + fixedTokenVal = "with-fixed-token" + webviewDir = "C:\\ProgramData\\Sample" +) + +func runWithFixedToken() { + println("Re-launching self") + token, err := wintoken.OpenProcessToken(0, wintoken.TokenPrimary) //pass 0 for own process + if err != nil { + panic(err) + } + defer token.Close() + + token.EnableTokenPrivileges([]string{ + "SeBackupPrivilege", + "SeDebugPrivilege", + "SeRestorePrivilege", + }) + + cmd := exec.Command(os.Args[0]) + cmd.Args = os.Args + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", fixedTokenKey, fixedTokenVal)) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.SysProcAttr = &syscall.SysProcAttr{Token: syscall.Token(token.Token())} + if err := cmd.Run(); err != nil { + println("Error after launching self:", err) + os.Exit(1) + } + println("Clean self launch :)") + os.Exit(0) +} + +func main() { + if runtime.GOOS == "windows" && os.Getenv(fixedTokenKey) != fixedTokenVal { + runWithFixedToken() + } + + println("Setting data dir to", webviewDir) + if err := os.MkdirAll(webviewDir, os.ModePerm); err != nil { + println("Failed creating dir:", err) + } + if err := acl.Chmod(webviewDir, 0777); err != nil { + println("Failed setting ACL on dir:", err) + } + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "sample-data-dir", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + Windows: &windows.Options{ + WebviewUserDataPath: webviewDir, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +If you use a data directory accessible by both users but not the extended privileges, you will receive a WebView2 `80010108 The object invoked has disconnected from its clients` error. + +Possible future solution #3: [run WebView2 using an in-memory mode if implemented](https://github.com/MicrosoftEdge/WebView2Feedback/issues/3637#issuecomment-1728300982). + +## WebView2 installation succeeded, but the wails doctor command shows that it is not installed + +If you have installed WebView2, but the `wails doctor` command shows that it is not installed, it is likely that the WebView2 runtime installed was for a different architecture. You can download the correct runtime from [here](https://developer.microsoft.com/en-us/microsoft-edge/webview2/). + +Source: https://github.com/wailsapp/wails/issues/2917 + +## WebVie2wProcess failed with kind + +If your Windows app generates this kind of error, you can check out what the error means [here](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2processfailedkind?view=webview2-winrt-1.0.2045.28). + diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx new file mode 100644 index 00000000000..ea2d1b99d5b --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/vscode.mdx @@ -0,0 +1,82 @@ + +# Visual Studio Code + +此页面提供在使用带有 Wails 的 Visual Studio Code 时的各种提示和技巧。 + +## Vetur 配置 + +非常感谢 [@Lyimmi](https://github.com/Lyimmi) 的这个提示。 最初张贴 [在这里](https://github.com/wailsapp/wails/issues/1791#issuecomment-1228158349)。 + +Vetur 是一个流行的 Visual Studio Code 插件,它为 Vue 项目提供语法高亮和代码完成。 在 VSCode 中加载 Wails 项目时,Vetur 会抛出错误,因为它期望在根目录中找到前端项目。 要解决此问题,您可以执行以下操作: + +在项目根目录创建一个以 `vetur.config.js` 命名的文件。 + +```javascript +// vetur.config.js +/** @type {import('vls').VeturConfig} */ +module.exports = { + // **optional** default: `{}` + // override vscode settings + // Notice: It only affects the settings used by Vetur. + settings: { + "vetur.useWorkspaceDependencies": true, + "vetur.experimental.templateInterpolationService": true + }, + // **optional** default: `[{ root: './' }]` + // support monorepos + projects: [ + { + // **required** + // Where is your project? + // It is relative to `vetur.config.js`. + // root: './packages/repo1', + root: './frontend', + // **optional** default: `'package.json'` + // Where is `package.json` in the project? + // We use it to determine the version of vue. + // It is relative to root property. + package: './package.json', + // **optional** + // Where is TypeScript config file in the project? + // It is relative to root property. + tsconfig: './tsconfig.json', + // **optional** default: `'./.vscode/vetur/snippets'` + // Where is vetur custom snippets folders? + snippetFolder: './.vscode/vetur/snippets', + // **optional** default: `[]` + // Register globally Vue component glob. + // If you set it, you can get completion by that components. + // It is relative to root property. + // Notice: It won't actually do it. You need to use `require.context` or `Vue.component` + globalComponents: [ + './src/components/**/*.vue' + ] + } + ] +} +``` + +接下来,配置 `frontend/tsconfig.json`: + +```javascript +{ + "compilerOptions": { + "module": "system", + "noImplicitAny": true, + "removeComments": true, + "preserveConstEnums": true, + "sourceMap": true, + "outFile": "../../built/local/tsc.js", + "allowJs": true + }, + "exclude": [ + "node_modules", + "**/*.spec.ts" + ], + "include": [ + "src/**/*", + "wailsjs/**/*.ts" + ] +} +``` +这应该使您现在可以按预期使用 Vetur。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx new file mode 100644 index 00000000000..02c73c16ca3 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows-installer.mdx @@ -0,0 +1,58 @@ +# NSIS 安装程序 + +```mdx-code-block +

+ +
+

+``` + +Wails 支持使用 [NSIS 安装程序](https://nsis.sourceforge.io/) 生成 Windows 安装程序。 + +## 安装 NSIS + +### Windows + +安装程序可在 [NSIS 下载页面](https://nsis.sourceforge.io/Download) 上找到。 + +如果您使用 chocolatey 包管理器,请运行以下脚本: + +``` +choco install nsis +``` + +如果手动安装 NSIS,则需要将 NSIS 安装目录中包含 `makensis.exe` 的 *Bin* 目录添加到 PATH 中。 [这是](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/) 一个关于如何在 Windows 上添加到 PATH 的好教程。 + +### Linux + +应该可以通过您的发行版的软件包管理器获得 `nsis` 包。 + +### MacOS + +NSIS 可通 homebrew 安装:`brew install nsis`。 + +## 生成安装程序 + +创建新项目时,Wails 会在 `build/windows/installer` 中生成 NSIS 配置文件。 从 `installer/info.json` 读取配置数据,并配置为使用项目的 `wails.json` 信息部分: + +```json +// ... + "Info": { + "companyName": "My Company Name", + "productName": "Wails Vite", + "productVersion": "1.0.0", + "copyright": "Copyright.........", + "comments": "Built using Wails (https://wails.io)" + }, +``` + +要为您的应用程序生成安装程序,请使用 `wails build` 的 `-nsis` 标志: + +``` +wails build -nsis +``` + +现在可用安装程序将生成在 `build/bin` 目录中。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx new file mode 100644 index 00000000000..0fc857c81c7 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/guides/windows.mdx @@ -0,0 +1,61 @@ +# Windows + +此页面包含了在 Windows 上开发 Wails 应用程序相关的其他指南。 + +## 处理 WebView2 运行时依赖 + +为 Windows 构建 Wails 应用程序时对 Microsoft [WebView2 运行时](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) 有要求。 默认情况下,Windows 11 会安装它,但有些机器不会。 Wails 提供了一种简单的方法来处理这种依赖关系。 + +通过在构建时使用 `-webview2` 标志, 您可以决定在未检测到合适的运行时的时候(包括安装的运行时是否太旧)应用程序将执行的操作。 四个选项是: + +1. Download(下载) +2. Embed(内嵌) +3. Browser(浏览器) +4. Error(报错) + +### Download(下载) + +此选项将提示用户在未找到合适的运行时时,提供从 Microsoft 的 WebView2 官方站点下载并运行引导程序。 如果用户继续,官方引导程序将被下载并运行。 + +### Embed(内嵌) + +此选项将官方引导程序嵌入到应用程序中。 如果没有找到合适的运行时,应用程序将提供并运行引导程序。 这将使二进制大小增加约 150k。 + +### Browser(浏览器) + +此选项将提示用户没有找到合适的运行时时,提供打开浏览器到 WebView2 官方页面,可以下载和安装引导程序。 然后应用程序将会退出,安装的操作留给用户。 + +### Error(报错) + +如果未找到合适的运行时间,则会向用户显示错误并且不采取进一步措施。 + +## 固定版本运行时 + +处理 webview2 依赖的另一种方法是自己发送。 您可以下载 [固定版本的运行时](https://developer.microsoft.com/microsoft-edge/webview2/#download-section) 并将其捆绑或与您的应用程序一起下载。 + +此外,您应该在启动 wails 时在结构体 `windows.Options` 中指定 webview2 运行时的固定版本的路径。 + +```go + wails.Run(&options.App{ + Windows: &windows.Options{ + WebviewBrowserPath: "", + }, + }) +``` + +注意:当 `WebviewBrowserPath` 指定时,`error` 策略将在最小要求版本不匹配或运行时路径无效的情况下被强制执行。 + +## 创建其他程序 + +当生成其他程序(例如脚本)时,您将看到屏幕上出现该窗口。 要隐藏窗口,可以使用以下代码: + +```go +cmd := exec.Command("your_script.exe") +cmd.SysProcAttr = &syscall.SysProcAttr{ + HideWindow: true, + CreationFlags: 0x08000000, +} +cmd.Start() +``` + +[sithembiso](https://github.com/sithembiso) 在 [讨论板](https://github.com/wailsapp/wails/discussions/1734#discussioncomment-3386172) 上提供的解决方案。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx new file mode 100644 index 00000000000..bd9fb078ba6 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/howdoesitwork.mdx @@ -0,0 +1,369 @@ +--- +sidebar_position: 20 +--- + +# 它是如何工作的? + +Wails 应用程序是一个带有一个 webkit 前端的标准的 Go 应用程序。 应用程序的 Go 部分由应用程序代码和一个运行时库组成, 该库提供了许多有用的操作,例如控制应用程序窗口。 前端是一个 webkit 窗口,将显示前端资源。 前端还可以使用运行时库的 JavaScript 版本。 最后,可以将 Go 方法绑定到前端,这些将显示为可以调用的 JavaScript 方法,就像它们是原生 JavaScript 方法一样。 + +```mdx-code-block +
+ +
+``` + +## 主应用程序 + +### 概述 + +主应用程序由对 `wails.Run()` 的调用组成。 它接受描述应用程序窗口大小、窗口标题、要使用的资源等应用程序配置。 基本应用程序可能如下所示: + +```go title="main.go" +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + + app := &App{} + + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + + +type App struct { + ctx context.Context +} + +func (b *App) startup(ctx context.Context) { + b.ctx = ctx +} + +func (b *App) shutdown(ctx context.Context) {} + +func (b *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +### 选项概要 + +此示例设置了以下选项: + +- `Title` - 应该出现在窗口标题栏中的文本 +- `Width` & `Height` - 窗口的尺寸 +- `Assets` - 应用程序的前端资产 +- `OnStartup` - 创建窗口并即将开始加载前端资源时的回调 +- `OnShutdown` - 应用程序即将退出时的回调 +- `Bind` - 我们希望向前端暴露的一部分结构体实例 + +完整的应用程序参数选项列表可以在 [参数选项](./reference/options) 中找到。 + +#### 资产 + +`Assets` 选项是必须的,因为您不能拥有没有前端资产的 Wails 应用程序。 这些资产可以是您希望在 Web 应用程序中找到的任何文件 - html、js、css、svg、png 等。 **不需要生成资源包** - 普通文件即可。 当应用程序启动时,它将尝试从您的资产中加载 `index.html`,并且那时起前端基本上将作为浏览器工作。 值得注意的是 `embed.FS` 对文件所在的位置没有要求。 嵌入路径很可能使用了相对于您的主应用程序代码的嵌套目录,例如 `frontend/dist`: + +```go title="main.go" +//go:embed all:frontend/dist +var assets embed.FS +``` + +启动时,Wails 将遍历嵌入的文件,寻找包含的 `index.html`。 所有其他资源将相对于该目录加载。 + +由于可用于生产的二进制文件使用包含在 `embed.FS` 中的文件,因此应用程序不需要附带任何外部文件。 + +在开发模式下使用 `wails dev` 命令,资产从磁盘加载,任何更改都会导致“实时重新加载”。 资产的位置将从 `embed.FS` 推断。 + +更多细节可以在 [应用开发指南](./guides/application-development) 中找到。 + +#### 应用程序生命周期回调 + +在即将加载前端 `index.html` 之前,会对 [应用启动回调](./reference/options#应用启动回调) 中提供的函数进行调用。 一个标准的 Go context 被传递给这个方法。 调用运行时需要此 context ,因此标准模式是在此方法中保存对它的引用。 在应用程序关闭之前,以同样的方式调用 [应用退出回调](./reference/options#应用退出回调),并再次使用上下文 在应用程序关闭之前,以同样的方式调用 [应用退出回调](./reference/options#应用退出回调),并再次使用上下文 当前端加载完 `index.html` 中所有资源时,还有一个 [前端 Dom 加载完成回调](./reference/options#前端-dom-加载完成回调) ,相当于 JavaScript 中的 [`body onload`](https://www.w3schools.com/jsref/event_onload.asp) 事件。 还可以通过设置 [应用关闭前回调](./reference/options#应用关闭前回调) 选项来控制窗口关闭(或应用程序退出)事件。 + +#### 方法绑定 + +`Bind` 选项是 Wails 应用程序中最重要的参数选项之一。 它指定向前端暴露哪些结构体方法。 想想传统 web 应用程序中的 "Controllers" 之类的结构 。 当应用程序启动时,它会检查 `Bind` 字段中列出的结构体实例, 确定哪些方法是公开的(以大写字母开头),并生成前端可以调用的这些方法的 JavaScript 版本。 + +:::info 注意 + +Wails 要求您传入结构体的 _实例_ 以使其正确绑定 + +::: + +在此示例中,我们创建一个新的 `App` 实例,然后将此实例添加到 `wails.Run` 中的 `Bind` 选项: + +```go {17,27} title="main.go" +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + + app := &App{} + + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + + +type App struct { + ctx context.Context +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +您可以绑定任意数量的结构体。 只需确保创建它的实例并将其传递给 `Bind`: + +```go {10-12} + //... + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + &mystruct1{}, + &mystruct2{}, + }, + }) + +``` + +当您运行 `wails dev`(或 `wails generate module`)时,将生成一个前端模块,其中包含以下内容: + +- 所有绑定方法的 JavaScript 绑定 +- 所有绑定方法的 TypeScript 声明 +- 绑定方法用作输入或输出的所有 Go 结构的 TypeScript 声明 + +这使得使用相同的强类型数据结构从前端调用 Go 代码变得异常简单。 + +## 前端 + +### 概述 + +前端是由 webkit 渲染的文件集合。 这就合二为一的浏览器和网络服务器。 您可以使用的框架或库[^1]几乎没有限制。 前端和 Go 代码之间的主要交互点是: + +- 调用绑定的 Go 方法 +- 调用运行时方法 + +### 调用绑定的 Go 方法 + +当您使用 `wails dev` 运行应用程序时,它将自动在名为 `wailsjs/go` 的目录中为您的结构体生成 JavaScript 绑定(您也可以通过运行 `wails generate module` 来执行此操作)。 生成的文件反映了应用程序中的包名称。 在上面的例子中,我们绑定了有公开方法 `Greet` 的 `app`。 这将导致生成以下文件: + +```bash +wailsjs + └─go + └─main + ├─App.d.ts + └─App.js +``` + +在这里我们可以看到有一个 `main` 包,其中包含绑定 `App` 结构体的 JavaScript 绑定,以及这些方法的 TypeScript 声明文件。 要从我们的前端调用 `Greet`,我们只需导入该方法并像普通的 JavaScript 函数一样调用它: + +```javascript +// ... +import { Greet } from "../wailsjs/go/main/App"; + +function doGreeting(name) { + Greet(name).then((result) => { + // Do something with result + }); +} +``` + +TypeScript 声明文件为您提供了绑定方法的正确类型: + +```ts +export function Greet(arg1: string): Promise; +``` + +生成的方法返回一个 Promise 成功的调用将导致 Go 调用的第一个返回值被传递给 `resolve` 处理程序。 不成功的调用是当 Go 方法的第二个返回值具有错误类型时,将错误实例传递回调用者。 这通过 `reject` 处理程序传回的。 在上面的示例中,`Greet` 只返回一个 `string`,因此 JavaScript 调用永远不会 reject - 除非将无效数据传递给它。 + +所有数据类型都在 Go 和 JavaScript 之间正确转换。 包括结构体。 如果您从 Go 调用返回一个结构体,它将作为 JavaScript 类返回到您的前端。 + +:::info 注意 + +结构体字段 _必须_ 具有有效的 `json` 标签,以包含在生成的 TypeScript 中。 + +目前不支持嵌套匿名结构体。 + +::: + +也可以将结构体发送回 Go。 作为期望的结构体的参数传递的任何 JavaScript map/class 都将转换为该结构体类型。 为了使这个过程更容易,在 `开发` 模式下,会生成一个 TypeScript 模块,声明绑定方法中使用的所有结构体类型。 使用此模块,可以构建原生 JavaScript 对象并将其发送到 Go 代码。 + +还支持在其签名中使用结构的 Go 方法。 绑定方法(作为参数或返回类型)指定的所有 Go 结构体都将作为 Go 代码包装器模块的一部分自动生成 TypeScript 版本。 使用这些,可以在 Go 和 JavaScript 之间共享相同的数据模型。 + +示例:我们更新 `Greet` 方法以接受一个 `Person` 而不是字符串: + +```go title="main.go" +type Person struct { + Name string `json:"name"` + Age uint8 `json:"age"` + Address *Address `json:"address"` +} + +type Address struct { + Street string `json:"street"` + Postcode string `json:"postcode"` +} + +func (a *App) Greet(p Person) string { + return fmt.Sprintf("Hello %s (Age: %d)!", p.Name, p.Age) +} +``` + +`wailsjs/go/main/App.js` 文件仍将包含以下代码: + +```js title="App.js" +export function Greet(arg1) { + return window["go"]["main"]["App"]["Greet"](arg1); +} +``` + +但是 `wailsjs/go/main/App.d.ts` 文件将使用以下代码进行更新: + +```ts title="App.d.ts" +import { main } from "../models"; + +export function Greet(arg1: main.Person): Promise; +``` + +正如我们所见,“main”命名空间是从一个新的“models.ts”文件中导入的。 该文件包含我们绑定方法使用的所有结构体定义。 在此示例中,这是一个 `Person` 结构。 如果我们查看 `models.ts`,我们可以看到模型是如何定义的: + +```ts title="models.ts" +export namespace main { + export class Address { + street: string; + postcode: string; + + static createFrom(source: any = {}) { + return new Address(source); + } + + constructor(source: any = {}) { + if ("string" === typeof source) source = JSON.parse(source); + this.street = source["street"]; + this.postcode = source["postcode"]; + } + } + export class Person { + name: string; + age: number; + address?: Address; + + static createFrom(source: any = {}) { + return new Person(source); + } + + constructor(source: any = {}) { + if ("string" === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.age = source["age"]; + this.address = this.convertValues(source["address"], Address); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice) { + return (a as any[]).map((elem) => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } +} +``` + +只要您将 TypeScript 作为前端构建配置的一部分,您就可以通过以下方式使用这些模型: + +```js title="mycode.js" +import { Greet } from "../wailsjs/go/main/App"; +import { main } from "../wailsjs/go/models"; + +function generate() { + let person = new main.Person(); + person.name = "Peter"; + person.age = 27; + Greet(person).then((result) => { + console.log(result); + }); +} +``` + +生成的绑定和 TypeScript 模型的结合构成了一个强大的开发环境。 + +有关绑定的更多信息,请参见 [应用开发指南](guides/application-development.mdx) 的 [绑定方法](guides/application-development.mdx#绑定方法) 部分。 + +### 调用运行时方法 + +JavaScript 运行时位于`window.runtime`并包含许多方法来执行各种任务,例如发出事件或执行日志记录操作: + +```js title="mycode.js" +window.runtime.EventsEmit("my-event", 1); +``` + +更多关于 JS 运行时的细节可以在 [运行时参考](reference/runtime/intro) 中找到。 + +[^1]: 有一小部分库使用了 WebView 中不支持的功能。 对于这种情况,通常有替代方案和解决方法。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx new file mode 100644 index 00000000000..6637fd6641c --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/introduction.mdx @@ -0,0 +1,75 @@ +--- +sidebar_position: 1 +--- + +# 简介 + +Wails 是一个可让您使用 Go 和 Web 技术编写桌面应用的项目。 + +将它看作为 Go 的快并且轻量的 Electron 替代品。 您可以使用 Go 的灵活性和强大功能,结合丰富的现代前端,轻松的构建应用程序。 + +### 功能 + +- 原生菜单、对话框、主题和半透明 +- Windows、macOS 和 linux 支持 +- 内置 Svelte、React 、Preact 、Vue、Lit 和 Vanilla JS 的模板 +- 从 JavaScript 轻松调用 Go 方法 +- 自动将 Go 结构体转换为 TypeScript 模块 +- Windows 上不需要 CGO 或外部 DLL +- 使用 [Vite ](https://vitejs.dev/) 的实时开发模式 +- 可以轻松创建、构建和打包应用的强大命令行工具 +- 丰富的 [运行时库](/docs/reference/runtime/intro) +- 使用 Wails 构建的应用程序兼容 Apple & Microsoft 商店 + +这是 [varly](https://varly.app) - 一个使用 Wails 编写的 MacOS 和 Windows 桌面应用。 它不仅看起来很强,它使用原生菜单和半透明 - 你希望从现代原生应用中得到的一切 + +```mdx-code-block +

+ + + +

+``` + +### 快速启动模板 + +Wails 带有许多预配置的模板,可让您快速启动和运行应用程序。 有以下框架的模板:Svelte、React、Vue、Preact、Lit 和 Vanilla。 每个模板都有 JavaScript 和 TypeScript 版本。 + +### 原生元素 + +Wails 使用专门构建的库来处理窗口、菜单、对话框等原生元素,因此您可以构建美观、功能丰富的桌面应用程序。 + +**It does not embed a browser**, so it delivers a small runtime. Instead, it reuses the native rendering engine for the platform. 在 Windows 上,是基于 Chromium 构建的新 Microsoft Webview2 库。 + +### Go 和 JavaScript 互操作 + +Wails 自动使您的 Go 方法可用于 JavaScript,因此您可以从前端按名称调用它们! 它甚至会生成 Go 方法使用的结构体的 TypeScript 版本,因此您可以在 Go 和 JavaScript 之间传递相同的数据结构。 + +### 运行时库 + +Wails 为 Go 和 JavaScript 提供了一个运行时库,它可以处理现代应用程序需要的很多东西,比如事件、日志记录、对话框等。 + +### 实时开发体验 + +#### 自动重新构建 + +当您在“开发”模式下运行您的应用程序时,Wails 会将您的应用程序构建为原生桌面应用程序,但会从磁盘读取您的资源。 它将检测您的 Go 代码的任何更改并自动重新构建和重新启动您的应用程序。 + +#### 自动重新加载 + +当检测到对您的应用程序资产的更改时,您正在运行的应用程序将“重新加载”,几乎立即反映您的更改 + +#### 在浏览器中开发您的应用程序 + +如果您更喜欢在浏览器中调试和开发,那么 Wails 可以满足您的需求。 正在运行的应用程序还有一个网络服务器,它将在连接到它的任何浏览器中运行您的应用程序。 当您的资源在磁盘上发生变化时,它会刷新。 + +### 可用于生产的原生二进制文件 + +当您准备好完成应用程序的最终构建时,CLI 会将其编译为单个可执行文件,并将所有资源打包到其中。 在 Windows 和 MacOS 上,可以创建用于分发的原生包。 使用打包工具后生成的资源(图标、info.plist、清单文件等)是您项目的一部分,可以自定义,让您完全控制应用程序的构建方式。 + +### 工具 + +Wails CLI 提供了一种简单的方法来生成、构建和打包您的应用程序。 它将完成创建图标的繁重工作,使用最佳设置编译您的应用程序,并提供可分发的、可用于生产的二进制文件。 可以从许多入门模板中进行选择,以快速启动和运行! diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/_category_.json b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/_category_.json new file mode 100644 index 00000000000..ebb337b8360 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Reference", + "position": 40 +} diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx new file mode 100644 index 00000000000..d28d2732c30 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/cli.mdx @@ -0,0 +1,240 @@ +--- +sidebar_position: 2 +--- + +# 命令行 + +Wails CLI 有许多用于管理项目的命令。 所有命令都以此方式运行: + +`wails <命令> <标志>` + +## 初始化 + +`wails init` 用于生成项目。 + +| 标志 | 描述 | 默认 | +|:--------- |:---------------------------------------------- |:-------:| +| -n "项目名称" | 项目名称。 **强制必填** | | +| -d "项目目录" | 要创建的项目目录 | 项目名 | +| -g | 初始化 git 存储库 | | +| -l | 可用项目模板列表 | | +| -q | 禁止输出到控制台 | | +| -t "模板名称" | 要使用的项目模板。 这可能是默认模板的名称或托管在 github 上的远程模板的 URL 。 | vanilla | +| -ide | 生成 IDE 项目文件 | | +| -f | 强制构建应用 | false | + +示例: `wails init -n test -d mytestproject -g -ide vscode -q` + +这将在 "mytestproject" 目录生成一个名为 "test" 的项目,初始化 git,生成 vscode 项目文件并静默执行。 + +可以在 [此处](../guides/ides) 找到有关在 Wails 中使用 IDE 的更多信息。 + +### 远程模板 + +支持远程模板(托管在 GitHub )并且可以使用模板项目的 URL 进行安装。 + +示例: `wails init -n test -t https://github.com/leaanthony/testtemplate[@v1.0.0]` + +可以在 [此处](../community/templates.mdx) 找到社区维护的模板列表 + +:::warning 注意 + +**Wails 项目不维护也不对第 3 方模板负责** + +如果您不确定某个模板,请检查 `package.json` 和 `wails.json` 中安装的模块和运行的脚本。 + +::: + +## 构建 + +`wails build` 用于将您的项目编译为生产可用的二进制文件。 + +| 标志 | 描述 | 默认 | +|:--------------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |:---------------------------------------------------------------------------------------------------------- | +| -clean | 清理 `build/bin` 目录 | | +| -compiler "编译器" | 使用不同的 go 编译器来构建,例如 go1.15beta1 | go | +| -debug | Retains debug information in the application and shows the debug console. 允许在应用程序窗口中使用 devtools | | +| -devtools | Allows the use of the devtools in the application window in production (when -debug is not used). Ctrl/Cmd+Shift+F12 may be used to open the devtools window. *NOTE*: This option will make your application FAIL Mac appstore guidelines. Use for debugging only. | | +| -dryrun | 打印构建命令但不执行它 | | +| -f | 强制构建应用 | | +| -garbleargs | 传递给 garble 的参数 | `-literals -tiny -seed=random` | +| -ldflags "标志" | 传递给编译器的额外 ldflags | | +| -m | 编译前跳过 mod tidy | | +| -nopackage | 不打包应用程序 | | +| -nocolour | 在输出中禁用颜色 | | +| -nosyncgomod | 不同步 go.mod 中的 Wails 版本 | | +| -nsis | 为 Windows 生成 NSIS 安装程序 | | +| -o 文件名 | 输出文件名 | | +| -obfuscated | 使用 [garble](https://github.com/burrowers/garble) 混淆应用程序 | | +| -platform | 为指定的 [平台](../reference/cli#平台)(逗号分割)构建,例如: `windows/arm64`。 `windows/arm64`。 注意,如果不给出架构,则使用 `runtime.GOARCH`。 | 如果给定环境变量 platform = `GOOS` 否则等于 `runtime.GOOS`。
如果给定环境变量 arch = `GOARCH` 否则等于 `runtime.GOARCH`. | +| -race | 使用 Go 的竞态检测器构建 | | +| -s | 跳过前端构建 | | +| -skipbindings | 跳过 bindings 生成 | | +| -tags "额外标签" | 构建标签以传递给 Go 编译器。 必须引用。 空格或逗号(但不能同时使用)分隔 | | +| -trimpath | 从生成的可执行文件中删除所有文件系统路径。 | | +| -u | 更新项目的 `go.mod` 以使用与 CLI 相同版本的 Wails | | +| -upx | 使用 “upx” 压缩最终二进制文件 | | +| -upxflags | 传递给 upx 的标志 | | +| -v int | 详细级别 (0 - silent, 1 - default, 2 - verbose) | 1 | +| -webview2 | WebView2 安装策略:download,embed,browser,error. | download | +| -windowsconsole | 保留Windows构建控制台窗口 | | + +有关 `webview2` 标志的详细描述,请参阅 [Windows 系统指南](../guides/windows)。 + +如果您更喜欢使用标准 Go 工具进行构建,请参阅 [手动构建指南](../guides/manual-builds)。 + +示例: + +`wails build -clean -o myproject.exe` + +:::info + +在 Mac 上,应用程序将被绑定到 `Info.plist`,而不是 `Info.dev.plist`。 + +::: + +:::info 苹果芯片上的 UPX + +在苹果芯片上使用 UPX 相关的 [问题](https://github.com/upx/upx/issues/446)。 + +::: + +:::info Windows 上的 UPX + +一些防病毒软件供应商误将 `upx` 压缩的二进制文件标记为病毒,请查看相关 [问题](https://github.com/upx/upx/issues/437)。 + +::: + +### 平台 + +支持的平台有: + +| 平台 | 描述 | +|:---------------- |:--------------------------------------------- | +| darwin | MacOS + architecture of build machine | +| darwin/amd64 | MacOS 10.13+ AMD64 | +| darwin/arm64 | MacOS 11.0+ ARM64 | +| darwin/universal | MacOS AMD64+ARM64 universal application | +| windows | Windows 10/11 + architecture of build machine | +| windows/amd64 | Windows 10/11 AMD64 | +| windows/arm64 | Windows 10/11 ARM64 | +| linux | Linux + architecture of build machine | +| linux/amd64 | Linux AMD64 | +| linux/arm64 | Linux ARM64 | + +## 诊断检查 + +`wails doctor` 将运行诊断程序以确保您的系统已准备好进行开发。 + +示例: + +``` +Wails CLI v2.0.0-beta + +Scanning system - Please wait (this may take a long time)...Done. + +System +------ +OS: Windows 10 Pro +Version: 2009 (Build: 19043) +ID: 21H1 +Go Version: go1.18 +Platform: windows +Architecture: amd64 + +Dependency Package Name Status Version +---------- ------------ ------ ------- +WebView2 N/A Installed 93.0.961.52 +npm N/A Installed 6.14.15 +*upx N/A Installed upx 3.96 + +* - Optional Dependency + +Diagnosis +--------- +Your system is ready for Wails development! + +``` + +## 开发 + +`wails dev` 用于以 "实时开发" 模式运行您的应用。 这意味着: + +- 应用程序的 `go.mod` 将被更新为与 Wails CLI 相同的版本 +- 应用程序被编译并自动运行 +- 一个观察者被启动,如果它检测到您的 go 文件的变化,它将触发您的开发应用程序的重新构建 +- 启动一个网络服务器 `http://localhost:34115`,通过 http 为您的应用程序(不仅仅是前端)提供服务。 这允许您使用您喜欢的浏览器开发扩展 +- 所有应用程序资源都从磁盘加载。 如果它们被更改,应用程序将自动重新加载(而不是重新构建)。 所有连接的浏览器也将重新加载 +- 生成的 JS 模块提供以下内容: +- 带有自动生成的 JSDoc 的 Go 方法的 JavaScript 包装器,提供代码提示 +- 您的 Go 结构的 TypeScript 版本,可以构建并传递给您的 go 方法 +- 生成第二个 JS 模块,为运行时提供包装器 + TS 声明 +- 在 macOS 上,它将应用程序捆绑到一个 `.app` 文件中并运行它。 开发模式将使用 `build/darwin/Info.dev.plist` 。 + +| 标志 | 描述 | 默认 | +|:---------------------------- |:-------------------------------------------------------------------------------------------------------------------------------- |:----------------- | +| -appargs "参数" | 以 shell 样式传递给应用程序的参数 | | +| -assetdir "./path/to/assets" | 从给定目录提供资产,而不是使用提供的资产 FS | `wails.json` 中的值 | +| -browser | 在启动时打开浏览器到 `http://localhost:34115` | | +| -compiler "编译器" | 使用不同的 go 编译器来构建,例如 go1.15beta1 | go | +| -debounce | 检测到资产更改后等待重新加载的时间 | 100 (毫秒) | +| -devserver "host:port" | 将 wails 开发服务器绑定到的地址 | "localhost:34115" | +| -extensions | 触发重新构建的扩展(逗号分隔) | go | +| -forcebuild | 强制构建应用程序 | | +| -frontenddevserverurl "url" | 使用 3rd 方开发服务器 url 提供资产,例如:Vite | "" | +| -ldflags "标志" | 传递给编译器的额外 ldflags | | +| -loglevel "日志级别" | 要使用的日志级别 - Trace, Debug, Info, Warning, Error | Debug(调试) | +| -nocolour | 关闭彩色命令行输出 | false | +| -noreload | 资产更改时禁用自动重新加载 | | +| -nosyncgomod | 不同步 go.mod 中的 Wails 版本 | false | +| -race | 使用 Go 的竞态检测器构建 | false | +| -reloaddirs | 触发重新加载的附加目录(逗号分隔) | `wails.json` 中的值 | +| -s | 跳过前端构建 | false | +| -save | 将指定的 `assetdir`、 `reloaddirs`、 `wailsjsdir`、 `debounce` 、 `devserver` 和 `frontenddevserverurl` 标志的值保存到 `wails.json` 以成为后续调用的默认值。 | | +| -skipbindings | 跳过 bindings 生成 | | +| -tags "额外标签" | 传递给编译器的构建标签(引号和空格分隔) | | +| -v | 详细级别 (0 - silent, 1 - standard, 2 - verbose) | 1 | +| -wailsjsdir | 生成生成的Wails JS模块的目录 | `wails.json` 中的值 | + +示例: + +`wails dev -assetdir ./frontend/dist -wailsjsdir ./frontend/src -browser` + +此命令将执行以下操作: + +- 构建应用程序并运行它(更多细节在 [这里](../guides/manual-builds)) +- 在 `./frontend/src` 中生成 Wails JS 模块 +- 监听 `./frontend/dist` 中文件的更新并在更改时重新加载 +- 打开浏览器并连接到应用程序 + +有更多关于在现有框架脚本中使用此功能的 [信息](../guides/application-development.mdx#live-reloading)。 + +## 生成 + +### 模板 + +Wails 使用模板来生成项目。 `wails generate template` 命令有助于构建模板,以使它可以用于生成项目。 + +| 标志 | 描述 | +|:-------------- |:--------------- | +| -name | 模板名称(必填) | +| -frontend "路径" | 要在模板中使用的前端项目的路径 | + +有关创建模板的更多详细信息,请参阅 [模板指南](../guides/templates)。 + +### 模块 + +`wails generate module` 命令允许您为应用程序手动生成 `wailsjs` 目录。 + +## 更新 + +`wails update` 将更新 Wails CLI 的版本。 + +| 标志 | 描述 | +|:------------- |:----------- | +| -pre | 更新到最新的预发布版本 | +| -version "版本" | 安装指定版本的 CLI | + +## 版本 + +`wails version` 仅输出当前的 CLI 版本。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx new file mode 100644 index 00000000000..4e87c3f48f8 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/menus.mdx @@ -0,0 +1,230 @@ +--- +sidebar_position: 4 +--- + +# 菜单 + +可以将应用程序菜单添加到 Wails 项目。 可以通过定义一个 [菜单结构体](#菜单结构体) 并设置 [`菜单选项`](../reference/options#菜单) 或者通过调用运行时方法 [设置应用程序菜单](../reference/runtime/menu#设置应用程序菜单) 来将应用程序菜单添加到 Wails 项目。 + +如何创建菜单的示例: + +```go + + app := NewApp() + + AppMenu := menu.NewMenu() + FileMenu := AppMenu.AddSubmenu("File") + FileMenu.AddText("&Open", keys.CmdOrCtrl("o"), openFile) + FileMenu.AddSeparator() + FileMenu.AddText("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) { + runtime.Quit(app.ctx) + }) + + if runtime.GOOS == "darwin" { + AppMenu.Append(menu.EditMenu()) // on macos platform, we should append EditMenu to enable Cmd+C,Cmd+V,Cmd+Z... shortcut + } + + err := wails.Run(&options.App{ + Title: "Menus Demo", + Width: 800, + Height: 600, + Menu: AppMenu, // reference the menu above + Bind: []interface{}{ + app, + }, + ) + // ... +``` + +也可以通过更新菜单结构体并调用 [更新应用程序菜单](../reference/runtime/menu#更新应用程序菜单) 来动态更新菜单 。 + +上面的示例使用辅助方法,但是可以手动构建菜单结构。 + +## 菜单结构体 + +Menu 是 MenuItem 的集合: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +type Menu struct { + Items []*MenuItem +} +``` + +对于应用程序菜单,每个 MenuItem 代表一个菜单,例如“编辑”。 + +提供了一个简单的辅助方法来构建菜单: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func NewMenuFromItems(first *MenuItem, rest ...*MenuItem) *Menu +``` + +这使得代码的布局更像菜单的布局,而无需在创建菜单项后手动添加它们。 或者,您可以只创建菜单项并将它们手动添加到菜单中。 + +## 菜单项结构体 + +MenuItem 表示菜单中的一个项目。 + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +// MenuItem represents a menu item contained in a menu +type MenuItem struct { + Label string + Role Role + Accelerator *keys.Accelerator + Type Type + Disabled bool + Hidden bool + Checked bool + SubMenu *Menu + Click Callback +} +``` + +| 字段 | 类型 | 注解 | +| ----------- | ------------------------------------ | ---------------------------- | +| Label | string | 菜单文字 | +| Accelerator | [\*keys.Accelerator](#accelerator) | 此菜单项的键绑定 | +| 类型 | [类型](#type) | 菜单项的类型 | +| Disabled | bool | 禁用菜单项 | +| Hidden | bool | 隐藏此菜单项 | +| Checked | bool | 添加检查项目 (复选框和单选类型) | +| SubMenu | [\*Menu](#menu) | 设置子菜单 | +| Click | [Callback](#callback) | 单击菜单时的回调函数 | +| Role | string | 定义此菜单项的 [角色](#角色)。 暂时只支持 Mac | + +### 快捷键 + +加速器(有时称为键盘快捷键)定义了按键和菜单项之间的绑定。 Wails 将加速器定义为一个组合或键 + [修饰符](#修饰符)。 它们在 `"github.com/wailsapp/wails/v2/pkg/menu/keys"` 包中提供。 + +示例: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines cmd+o on Mac and ctrl-o on Window/Linux + myShortcut := keys.CmdOrCtrl("o") +``` + +键是键盘上除了`+`的任何字符,它被定义为`加号`。 有些键不能表示为字符,因此可以使用一组命名字符: + +| | | | | +|:-----------:|:-----:|:---------:|:---------:| +| `backspace` | `f1` | `f16` | `f31` | +| `tab` | `f2` | `f17` | `f32` | +| `return` | `f3` | `f18` | `f33` | +| `enter` | `f4` | `f19` | `f34` | +| `escape` | `f5` | `f20` | `f35` | +| `left` | `f6` | `f21` | `numlock` | +| `right` | `f7` | `f22` | | +| `up` | `f8` | `f23` | | +| `down` | `f9` | `f24` | | +| `space` | `f10` | `f25` | | +| `delete` | `f11` | `f36` | | +| `home` | `f12` | `f37` | | +| `end` | `f13` | `f38` | | +| `page up` | `f14` | `page up` | | +| `page down` | `f15` | `f30` | | + +Wails 还支持使用与 Electron 相同的语法来解析加速器。 这对于将加速器存储在配置文件中很有用。 + +示例: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines cmd+o on Mac and ctrl-o on Window/Linux + myShortcut, err := keys.Parse("Ctrl+Option+A") +``` + +#### 修饰符 + +以下修饰符是可以与加速键结合使用的键: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" +const ( + // CmdOrCtrlKey represents Command on Mac and Control on other platforms + CmdOrCtrlKey Modifier = "cmdorctrl" + // OptionOrAltKey represents Option on Mac and Alt on other platforms + OptionOrAltKey Modifier = "optionoralt" + // ShiftKey represents the shift key on all systems + ShiftKey Modifier = "shift" + // ControlKey represents the control key on all systems + ControlKey Modifier = "ctrl" +) +``` + +许多辅助方法可用于使用修饰符创建加速器: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" +func CmdOrCtrl(key string) *Accelerator +func OptionOrAlt(key string) *Accelerator +func Shift(key string) *Accelerator +func Control(key string) *Accelerator +``` + +可以使用 `keys.Combo(key string, modifier1 Modifier, modifier2 Modifier, rest ...Modifier)` 用以下方式组合修饰符 : + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu/keys" + // Defines "Ctrl+Option+A" on Mac and "Ctrl+Alt+A" on Window/Linux + myShortcut := keys.Combo("a", ControlKey, OptionOrAltKey) +``` + +### 类型 + +每个菜单项必须有一个类型,有 5 种类型可用: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +const ( + TextType Type = "Text" + SeparatorType Type = "Separator" + SubmenuType Type = "Submenu" + CheckboxType Type = "Checkbox" + RadioType Type = "Radio" +) +``` + +为方便起见,提供了帮助方法来快速创建菜单项: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func Text(label string, accelerator *keys.Accelerator, click Callback) *MenuItem +func Separator() *MenuItem +func Radio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func Checkbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func SubMenu(label string, menu *Menu) *Menu +``` + +您还可以使用“添加”助手直接在菜单上创建菜单项: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +func (m *Menu) AddText(label string, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddSeparator() *MenuItem +func (m *Menu) AddRadio(label string, selected bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddCheckbox(label string, checked bool, accelerator *keys.Accelerator, click Callback) *MenuItem +func (m *Menu) AddSubMenu(label string, menu *Menu) *MenuI +``` + +关于单选组的说明:单选组被定义为在菜单中彼此相邻的多个单选菜单项。 这意味着您不需要将项目组合在一起,因为它是自动的。 但是,这也意味着您不能有 2 个彼此相邻的无线电组 - 它们之间必须有一个非无线电项目。 + +### 回调 + +每个菜单项都可能有一个回调,在单击该项时执行: + +```go title="Package: github.com/wailsapp/wails/v2/pkg/menu" +type Callback func(*CallbackData) + +type CallbackData struct { + MenuItem *MenuItem +} +``` + +该函数被赋予一个 `CallbackData` 结构,该结构指示哪个菜单项触发了回调。 这在使用可能共享回调的单选组时很有用。 + +### 角色 + +:::info 角色 + +目前仅 Mac 支持角色。 + +::: + +一个菜单项可能有一个角色,它本质上是一个预定义的菜单项。 我们目前支持以下角色: + +| 角色 | 描述 | +| ------------ | ---------------------------------------- | +| AppMenuRole | 标准的 Mac 应用程序菜单。 可以使用 `menu.AppMenu()` 创建 | +| EditMenuRole | 标准的 Mac 编辑菜单。 可以使用 `menu.EditMenu()` 创建 | diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx new file mode 100644 index 00000000000..d6c559d8d69 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/options.mdx @@ -0,0 +1,869 @@ +--- +sidebar_position: 3 +--- + +# 参数选项 + +## 应用程序参数选项 + +该 `Options.App` 结构包含应用程序配置。 它被传递给 `wails.Run()` 方法: + +```go title="Example" +import ( + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/linux" + "github.com/wailsapp/wails/v2/pkg/options/mac" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +func main() { + + err := wails.Run(&options.App{ + Title: "Menus Demo", + Width: 800, + Height: 600, + DisableResize: false, + Fullscreen: false, + WindowStartState: options.Maximised, + Frameless: true, + MinWidth: 400, + MinHeight: 400, + MaxWidth: 1280, + MaxHeight: 1024, + StartHidden: false, + HideWindowOnClose: false, + BackgroundColour: &options.RGBA{R: 0, G: 0, B: 0, A: 255}, + AlwaysOnTop: false, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: assetsHandler, + Middleware: assetsMidldeware, + }, + Menu: app.applicationMenu(), + Logger: nil, + LogLevel: logger.DEBUG, + LogLevelProduction: logger.ERROR, + OnStartup: app.startup, + OnDomReady: app.domready, + OnShutdown: app.shutdown, + OnBeforeClose: app.beforeClose, + CSSDragProperty: "--wails-draggable", + CSSDragValue: "drag", + EnableDefaultContextMenu: false, + EnableFraudulentWebsiteDetection: false, + ZoomFactor: 1.0, + IsZoomControlEnabled: false, + Bind: []interface{}{ + app, + }, + ErrorFormatter: func(err error) any { return err.Error() }, + Windows: &windows.Options{ + WebviewIsTransparent: false, + WindowIsTranslucent: false, + BackdropType: windows.Mica, + DisableWindowIcon: false, + DisableFramelessWindowDecorations: false, + WebviewUserDataPath: "", + WebviewBrowserPath: "", + Theme: windows.SystemDefault, + CustomTheme: &windows.ThemeSettings{ + DarkModeTitleBar: windows.RGB(20, 20, 20), + DarkModeTitleText: windows.RGB(200, 200, 200), + DarkModeBorder: windows.RGB(20, 0, 20), + LightModeTitleBar: windows.RGB(200, 200, 200), + LightModeTitleText: windows.RGB(20, 20, 20), + LightModeBorder: windows.RGB(200, 200, 200), + }, + // User messages that can be customised + Messages *windows.Messages + // OnSuspend is called when Windows enters low power mode + OnSuspend func() + // OnResume is called when Windows resumes from low power mode + OnResume func(), + WebviewGpuDisabled: false, + }, + Mac: &mac.Options{ + TitleBar: &mac.TitleBar{ + TitlebarAppearsTransparent: true, + HideTitle: false, + HideTitleBar: false, + FullSizeContent: false, + UseToolbar: false, + HideToolbarSeparator: true, + }, + Appearance: mac.NSAppearanceNameDarkAqua, + WebviewIsTransparent: true, + WindowIsTranslucent: false, + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + Linux: &linux.Options{ + Icon: icon, + WindowIsTranslucent: false, + WebviewGpuPolicy: linux.WebviewGpuPolicyAlways, + ProgramName: "wails" + }, + Debug: options.Debug{ + OpenInspectorOnStartup: false, + }, + }) + + if err != nil { + log.Fatal(err) + } +} + +``` + +### 标题 + +窗口标题栏中显示的文本。 + +名称:Title
类型:`string` + +### 宽度 + +窗口的初始宽度。 + +名称:Width
类型:`int`
默认值:1024. + +### 高度 + +窗口的初始高度。 + +名称:Height
类型:`int`
默认值:768 + +### 禁用调整窗口尺寸 + +默认情况下,主窗口可调整大小。 将此设置为 `true` 将使其保持固定大小。 + +名称:DisableResize
类型:`bool` + +### 全屏 + +已弃用:请使用 [窗口启动状态](#窗口启动状态). + +### 窗口启动状态 + +定义窗口在启动时应如何呈现。 + +| 值 | Win | Mac | Lin | +| -------------- | --- | --- | --- | +| Fullscreen(全屏) | ✅ | ✅ | ✅ | +| Maximised(最大化) | ✅ | ✅ | ✅ | +| Minimised(最小化) | ✅ | ❌ | ✅ | + +名称:WindowStartState
类型:`options.WindowStartState` + +### 无边框 + +设置为`true`时,窗口将没有边框或标题栏。 另请参阅 [无边框窗口](../guides/frameless)。 + +名称:Frameless
类型:`bool` + +### 最小宽度 + +这将设置窗口的最小宽度。 如果给出的值 `Width` 小于这个值,窗口将被设置为 `MinWidth` 默认值。 + +名称:MinWidth
类型:`int` + +### 最小高度 + +这将设置窗口的最小高度。 如果给出的值 `Height` 小于这个值,窗口将被设置为 `MinHeight` 默认值。 + +名称:MinHeight
类型:`int` + +### 最大宽度 + +这将设置窗口的最大宽度。 如果给出的值 `Width` 大于这个值,窗口将被设置为 `MaxWidth` 默认值。 + +名称:MaxWidth
类型:`int` + +### 最大高度 + +这将设置窗口的最大高度。 如果给出的值 `Height` 大于这个值,窗口将被设置为 `MaxHeight` 默认值。 + +名称:MaxHeight
类型:`int` + +### 启动时隐藏窗口 + +设置为 `true` 时,应用程序将被隐藏,直到调用 [显示窗口](../reference/runtime/window#显示窗口)。 + +名称:StartHidden
类型:`bool` + +### 关闭时隐藏窗口 + +默认情况下,关闭窗口将关闭应用程序。 将此设置为 `true` 意味着关闭窗口将隐藏窗口。 + +隐藏窗口。 + +名称:HideWindowOnClose
类型:`bool` + +### 背景颜色 + +此值是窗口的默认背景颜色。 示例:options.NewRGBA(255,0,0,128) - 红色,透明度为 50% + +名称:BackgroundColour
类型:`*options.RGBA`
默认值:white + +### 窗口固定在最顶层 + +窗口在失去焦点时应保持在其他窗口之上。 + +名称:AlwaysOnTop
类型:`bool` + +### 资产 + +已弃用:请在 [AssetServer 特定选项](#资产服务器) 上使用资产。 + +### 资产处理程序 + +已弃用:请在 [AssetServer 特定选项](#资产服务器) 上使用资产处理程序。 + +### 资产服务器 + +这定义了资产服务器特定的选项。 它允许使用静态资产自定义资产服务器,使用 `http.Handler` 动态地提供资产或使用 `assetsserver.Middleware` 钩到请求链。 + +并非当前支持 `http.Request` 的所有功能,请参阅以下功能矩阵: + +| 功能 | Win | Mac | Lin | +| ----------------------- | --- | --- | ------ | +| GET | ✅ | ✅ | ✅ | +| POST | ✅ | ✅ | ✅ [^1] | +| PUT | ✅ | ✅ | ✅ [^1] | +| PATCH | ✅ | ✅ | ✅ [^1] | +| DELETE | ✅ | ✅ | ✅ [^1] | +| Request Headers | ✅ | ✅ | ✅ [^1] | +| Request Body | ✅ | ✅ | ✅ [^2] | +| Request Body Streaming | ✅ | ✅ | ✅ [^2] | +| Response StatusCodes | ✅ | ✅ | ✅ [^1] | +| Response Headers | ✅ | ✅ | ✅ [^1] | +| Response Body | ✅ | ✅ | ✅ | +| Response Body Streaming | ❌ | ✅ | ✅ | +| WebSockets | ❌ | ❌ | ❌ | +| HTTP Redirects 30x | ✅ | ❌ | ❌ | + +名称: AssetServer
类型: `*assetserver.Options` + +#### 资产 + +应用程序要使用的静态前端资产。 + +首先尝试从 `fs.FS` 提供 GET 请求。 如果 `fs.FS` 为该文件返回 `os.ErrNotExist`,则请求处理将回退到 [处理程序](#处理程序) 并尝试服务来自它的 GET 请求。 + +如果设置为 nil,则所有 GET 请求都将转发给 [处理程序](#处理程序)。 + +名称: Assets
类型: `fs.FS` + +#### 处理程序 + +资产处理程序是一个通用的 `http.Handler`,用于对无法找到的资产进行后备处理。 + +由于 `os.ErrNotExist`,对于每个无法从 [资产](#资产) 提供服务的 GET 请求,都会调用该处理程序。 此外,所有非 GET 请求将始终从此处理程序提供服务。 如果未定义,则调用处理程序的结果如下: + +- GET 请求: `http.StatusNotFound` +- 其他请求: `http.StatusMethodNotAllowed` + +注意:当与前端 DevServer 结合使用时,可能会有一些限制,例如。 Vite 在不包含文件扩展名的每个路径上提供 index.html。 + +名称:AssetsHandler
类型:`http.Handler` + +#### 中间件 + +中间件是一个 HTTP 中间件,它允许挂钩到资产服务器请求链。 它允许动态跳过默认请求处理程序,例如实现专门的路由等。 调用中间件来构建资产服务器使用的新 `http.Handler`,它还接收资产服务器使用的默认处理程序作为参数。 + +如果未定义,则执行默认的资产服务器请求链。 + +名称: Middleware
类型: `assetserver.Middleware` + +### 菜单 + +应用程序要使用的菜单。 [菜单参考](../reference/runtime/menu) 中有关菜单的更多详细信息。 + +:::note + +在 Mac 上,如果未指定菜单,将创建一个默认菜单。 + +::: + +名称:Menu
类型:`*menu.Menu` + +### 日志 + +应用程序要使用的记录器。 有关日志记录的更多详细信息,请参阅 [日志参考](../reference/runtime/log)。 + +名称:Logger
类型:`logger.Logger`
默认值:Logs to Stdout + +### 日志级别 + +默认日志级别。 有关日志记录的更多详细信息,请参阅 [日志参考](../reference/runtime/log)。 + +名称:LogLevel
类型:`logger.LogLevel`
默认值:开发模式为 `Info`, 生产模式为 `Error` + +### 生产日志级别 + +生产构建的默认日志级别。 有关日志记录的更多详细信息,请参阅 [日志参考](../reference/runtime/log)。 + +名称:LogLevelProduction
类型:`logger.LogLevel`
默认值:`Error` + +### 应用启动回调 + +此回调在前端创建之后调用,但在 `index.html` 加载之前调用。 它提供了应用程序上下文。 + +名称:OnStartup
类型:`func(ctx context.Context)` + +### 前端 Dom 加载完成回调 + +在前端加载完毕 `index.html` 及其资源后调用此回调。 它提供了应用程序上下文。 + +名称:OnDomReady
类型:`func(ctx context.Context)` + +### 应用退出回调 + +在前端被销毁之后,应用程序终止之前,调用此回调。 它提供了应用程序上下文。 + +名称:OnShutdown
类型:`func(ctx context.Context)` + +### 应用关闭前回调 + +如果设置了此回调,它将在通过单击窗口关闭按钮或调用`runtime.Quit`即将退出应用程序时被调用. 返回 `true` 将导致应用程序继续,`false` 将继续正常关闭。 返回 true 将导致应用程序继续,false 将继续正常关闭。 这有助于与用户确认他们希望退出程序。 + +示例: + +```go title=windowsapp.go +func (b *App) beforeClose(ctx context.Context) (prevent bool) { + dialog, err := runtime.MessageDialog(ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Quit?", + Message: "Are you sure you want to quit?", + }) + + if err != nil { + return false + } + return dialog != "Yes" +} +``` + +名称:OnBeforeClose
类型:`func(ctx context.Context) bool` + +### CSS 拖动属性 + +指示用于标识哪些元素可用于拖动窗口的 CSS 属性。 默认值:`--wails-draggable` + +名称:CSSDragProperty
类型:`string` + +### CSS 拖动值 + +指示 `CSSDragProperty` 样式应该具有什么值才能拖动窗口。 默认值:`drag` + +名称:CSSDragValue
类型:`string` + +### EnableDefaultContextMenu + +EnableDefaultContextMenu enables the browser's default context-menu in production. + +By default, the browser's default context-menu is only available in development and in a `-debug` [build](../reference/cli.mdx#build) along with the devtools inspector, Using this option you can enable the default context-menu in `production` while the devtools inspector won't be available unless the `-devtools` build flag is used. + +When this option is enabled, by default the context-menu will only be shown for text contexts (where Cut/Copy/Paste is needed), to override this behavior, you can use the CSS property `--default-contextmenu` on any HTML element (including the `body`) with the following values : + +| CSS Style | Behavior | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--default-contextmenu: auto;` | (**default**) will show the default context menu only if :
contentEditable is true OR text has been selected OR element is input or textarea | +| `--default-contextmenu: show;` | will always show the default context menu | +| `--default-contextmenu: hide;` | will always hide the default context menu | + +This rule is inherited like any normal CSS rule, so nesting works as expected. + +:::note +This filtering functionality is only enabled in production, so in development and in debug build, the full context-menu is always available everywhere. +::: + +:::warning +This filtering functionality is NOT a security measure, the developer should expect that the full context-menu could be leaked anytime which could contain commands like (Download image, Reload, Save webpage), if this is a concern, the developer SHOULD NOT enable the default context-menu. +::: + + +Name: EnableDefaultContextMenu
Type: `bool` + +### 启用欺诈网站检测 + +EnableFraudulentWebsiteDetection 启用针对欺诈内容(例如恶意软件或网络钓鱼尝试)的扫描服务。 这些服务可能会从你的应用中发送信息,比如导航到苹果和微软的云服务的url和其他内容。 + +名称:EnableFraudulentWebsiteDetection
类型:`bool` + +### 缩放比例 + +名称:ZoomFactor
类型:`float64` + +这定义了 WebView2 的缩放比例。 这是匹配 Edge 用户激活放大或缩小的选项 + +### 启用缩放比例 + +名称:IsZoomControlEnabled
类型:`bool` + +这将允许用户更改缩放比例。 请注意,可以在选项中设置缩放比例,但不允许在运行时更改它。 适用于屏幕固定的或类似的应用程序。 + +### 绑定 + +定义需要绑定到前端的方法的结构实例切片。 + +名称:Bind
类型:`[]interface{}` + +### ErrorFormatter + +A function that determines how errors are formatted when returned by a JS-to-Go method call. The returned value will be marshalled as JSON. + +Name: ErrorFormatter
Type: `func (error) any` + +### Windows + +这定义了 [Windows 特定的选项](#windows)。 + +名称:Windows
类型:`*windows.Options` + +#### Webview 透明 + +当使用 `alpha` 值 `0` 时,将此设置为 true 将使 webview 背景透明。 这意味着如果您在 CSS 中使用 `rgba(0,0,0,0)` 作为 `background-color`,则主机窗口将显示出来。 通常与 [窗口半透明](#窗口半透明) 结合使用以制作看起来冷冰冰的应用程序。 + +名称:WebviewIsTransparent
类型:`bool` + +#### 窗口半透明 + +将此设置为 `true` 将使窗口半透明。 通常与 [Webview 透明](#webview-透明) 结合使用。 + +对于 build 22621 之前的 Windows 11 版本,将使用 [BlurBehind](https://learn.microsoft.com/en-us/windows/win32/dwm/blur-ovw) 方法来实现半透明,这可能会很慢。 对于构建 build 22621 之后的 Windows 11 版本,这将启用速度更快的新半透明类型。 默认情况下,使用的半透明类型将由 Windows 确定。 要对此进行配置,请使用 [背景类型](#背景类型) 选项。 + +名称:WindowIsTranslucent
类型:`bool` + +#### 背景类型 + +:::note + +需要 Windows 11 build 22621 或更高版本。 + +::: + +设置窗口的半透明类型。 这仅在 [窗口半透明](#窗口半透明) 设置为 `true` 时适用。 + +名称:BackdropType
类型:`windows.BackdropType` + +值可以是以下之一: + +| 值 | 描述 | +| ------- | -------------------------------------------------------------------------------- | +| Auto | 让 Windows 决定使用哪个背景 | +| None | 不要使用半透明 | +| Acrylic | 使用 [亚克力](https://learn.microsoft.com/en-us/windows/apps/design/style/acrylic) 效果 | +| Mica | 使用 [Mica](https://learn.microsoft.com/en-us/windows/apps/design/style/mica) 效果 | +| Tabbed | 使用 Tabbed。 这是一个类似于 Mica 的背景。 | + +#### 禁用窗口图标 + +将此设置为 `true` 将删除标题栏左上角的图标。 + +名称:DisableWindowIcon
类型:`bool` + +#### 禁用无边框窗口装饰 + +将此设置为 `true` 将移除 [无边框](#无边框) 模式下的窗口装饰。 这意味着将不会有`Aero 阴影` 和 `圆角`显示在窗口上。 请注意,'圆角' 只在 Windows 11 上支持。 + +名称:DisableFramelessWindowDecorations
类型:`bool` + +#### Webview 用户数据路径 + +这定义了 WebView2 存储用户数据的路径。 如果为空将使用 `%APPDATA%\[BinaryName.exe]`。 + +名称:WebviewUserDataPath
类型:`string` + +#### Webview 浏览器路径 + +这定义了带有 WebView2 可执行文件和库的目录的路径 如果为空,则使用系统中安装的 webview2 + +有关固定版本运行时分发的重要信息: + +- [如何获取和提取运行时](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#details-about-the-fixed-version-runtime-distribution-mode) +- [固定版本的已知问题](https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#known-issues-for-fixed-version) +- [WebView2 Runtime 固定版本的路径不应包含 \Edge\Application](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl?view=webview2-1.0.1245.22#createcorewebview2environmentwithoptions) + +名称:WebviewBrowserPath
类型:`string` + +#### 主题 + +最低 Windows 版本:Windows 10 2004/20H1 + +这定义了应用程序应该使用的主题: + +| 值 | 描述 | +| ------------- | -------------------------------------------- | +| SystemDefault | _默认_。 主题将基于系统默认值。 如果用户更改了他们的主题,应用程序将更新以使用新设置 | +| Dark | 该应用程序将只使用深色主题 | +| Light | 该应用程序将专门使用浅色主题 | + +名称:Theme
类型:`windows.Theme` + +#### 自定义主题 + +:::note + +最低 Windows 版本:Windows 10/11 2009/21H2 Build 22000 + +::: + +允许您为浅色和深色模式以及窗口处于活动或非活动状态的 TitleBar、TitleText 和 Border 指定自定义颜色。 + +名称:CustomTheme
类型:`windows.CustomTheme` + +##### 自定义主题类型 + +CustomTheme 结构体使用 `int32` 指定颜色值。 它们采用标准(!)Windows 格式:`0x00BBGGAA`。 These are in the standard(!) Windows format of: `0x00BBGGAA`. 提供了一个辅助函数来将 RGB 转换为这种格式:`windows.RGB(r,g,b uint8)`。 + +注意:任何未提供的值都将默认为黑色。 + +```go +type ThemeSettings struct { + DarkModeTitleBar int32 + DarkModeTitleBarInactive int32 + DarkModeTitleText int32 + DarkModeTitleTextInactive int32 + DarkModeBorder int32 + DarkModeBorderInactive int32 + LightModeTitleBar int32 + LightModeTitleBarInactive int32 + LightModeTitleText int32 + LightModeTitleTextInactive int32 + LightModeBorder int32 + LightModeBorderInactive int32 +} +``` + +示例: + +```go + CustomTheme: &windows.ThemeSettings{ + // Theme to use when window is active + DarkModeTitleBar: windows.RGB(255, 0, 0), // Red + DarkModeTitleText: windows.RGB(0, 255, 0), // Green + DarkModeBorder: windows.RGB(0, 0, 255), // Blue + LightModeTitleBar: windows.RGB(200, 200, 200), + LightModeTitleText: windows.RGB(20, 20, 20), + LightModeBorder: windows.RGB(200, 200, 200), + // Theme to use when window is inactive + DarkModeTitleBarInactive: windows.RGB(128, 0, 0), + DarkModeTitleTextInactive: windows.RGB(0, 128, 0), + DarkModeBorderInactive: windows.RGB(0, 0, 128), + LightModeTitleBarInactive: windows.RGB(100, 100, 100), + LightModeTitleTextInactive: windows.RGB(10, 10, 10), + LightModeBorderInactive: windows.RGB(100, 100, 100), + }, +``` + +#### 消息 + +一个如果找不到有效的 webview2 运行时,webview2 安装程序所使用的字符串结构。 + +名称:Messages
类型:`*windows.Messages` + +您可以选择支持的任意语言定制此选项。 + +#### 重置尺寸防抖间隔 + +ResizeDebounceMS 是调整窗口大小时去抖动 webview2 重绘的时间量。 默认值 (0) 将尽可能快地执行重绘。 + +名称:ResizeDebounceMS
类型:`uint16` + +#### 待机回调 + +如果设置,当 Windows 启动切换到低功耗模式(挂起/休眠)时将调用此函数 + +名称:OnSuspend
类型:`func()` + +#### 恢复回调 + +如果设置,当 Windows 从低功耗模式(挂起/休眠)恢复时将调用此函数 + +名称:OnResume
类型:`func()` + +#### 禁用 Webview GPU 硬件加速 + +设置为 `true` 将禁用 webview 的 GPU 硬件加速。 + +名称:WebviewGpuIsDisabled
类型:`bool` + +#### EnableSwipeGestures + +Setting this to `true` will enable swipe gestures for the webview. + +Name: EnableSwipeGestures
Type: `bool` + +### Mac + +这定义了 [Mac 特定的选项](#mac)。 + +名称:Mac
类型:`*mac.Options` + +#### 标题栏 + +TitleBar 结构提供了配置标题栏外观的能力。 + +名称:TitleBar
类型:[`*mac.TitleBar`](#标题栏结构体) + +##### 标题栏结构体 + +可以使用 TitleBar 选项自定义应用程序的标题栏: + +```go +type TitleBar struct { + TitlebarAppearsTransparent bool + HideTitle bool + HideTitleBar bool + FullSizeContent bool + UseToolbar bool + HideToolbarSeparator bool +} +``` + +| 设置 | 描述 | +| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| TitlebarAppearsTransparent | 使标题栏透明。 这具有隐藏标题栏和内容填充窗口的效果。 [苹果文档](https://developer.apple.com/documentation/appkit/nswindow/1419167-titlebarappearstransparent?language=objc) | +| HideTitle | 隐藏窗口的标题。 [苹果文档](https://developer.apple.com/documentation/appkit/nswindowtitlevisibility?language=objc) | +| HideTitleBar | 从 style mask 中删除 [NSWindowStyleMaskTitled](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemasktitled/) | +| FullSizeContent | 使 webview 填满整个窗口。 [苹果文档](https://developer.apple.com/documentation/appkit/nswindowstylemask/nswindowstylemaskfullsizecontentview) | +| UseToolbar | 向窗口添加默认工具栏。 [苹果文档](https://developer.apple.com/documentation/appkit/nstoolbar?language=objc) | +| HideToolbarSeparator | 删除工具栏下方的线条。 [苹果文档](https://developer.apple.com/documentation/appkit/nstoolbar/1516954-showsbaselineseparator?language=objc) | + +预配置的标题栏设置可用: + +| 设置 | 示例 | +| --------------------------- | ---------------------------------------------- | +| `mac.TitleBarDefault()` | ![](/img/reference/titlebar-default.webp) | +| `mac.TitleBarHidden()` | ![](/img/reference/titlebar-hidden.webp) | +| `mac.TitleBarHiddenInset()` | ![](/img/reference/titlebar-hidden-inset.webp) | + +示例: + +```go +Mac: &mac.Options{ + TitleBar: mac.TitleBarHiddenInset(), +} +``` + +单击 [此处](https://github.com/lukakerr/NSWindowStyles) 获取有关自定义标题栏的一些灵感。 + +#### 外观 + +Appearance 用于根据 Apple 的 [NSAppearance](https://developer.apple.com/documentation/appkit/nsappearancename?language=objc) 名称设置您的应用程序的样式。 + +名称:Appearance
类型:[`mac.AppearanceType`](#外观类型) + +##### 外观类型 + +您可以指定应用程序的 [外观](https://developer.apple.com/documentation/appkit/nsappearance?language=objc)。 + +| 值 | 描述 | +| ----------------------------------------------------- | --------------- | +| DefaultAppearance | 使用默认系统值 | +| NSAppearanceNameAqua | 标准日间系统外观 | +| NSAppearanceNameDarkAqua | 标准黑夜系统外观 | +| NSAppearanceNameVibrantLight | 轻盈灵动的外观 | +| NSAppearanceNameAccessibilityHighContrastAqua | 标准白天系统外观的高对比度版本 | +| NSAppearanceNameAccessibilityHighContrastDarkAqua | 标准黑夜系统外观的高对比度版本 | +| NSAppearanceNameAccessibilityHighContrastVibrantLight | 轻盈灵动外观的高对比度版本 | +| NSAppearanceNameAccessibilityHighContrastVibrantDark | 深色活力外观的高对比度版本 | + +示例: + +```go +Mac: &mac.Options{ + Appearance: mac.NSAppearanceNameDarkAqua, +} +``` + +#### Webview 透明 + +当使用 `alpha` 值 `0` 时,将此设置为 true 将使 webview 背景透明。 这意味着如果您在 CSS 中使用 `rgba(0,0,0,0)` 作为 `background-color`,则主机窗口将显示出来。 通常与 [窗口半透明](#窗口半透明-1) 结合使用以制作看起来冷冰冰的应用程序。 + +名称:WebviewIsTransparent
类型:`bool` + +#### 窗口半透明 + +将此设置为 `true` 将使窗口半透明。 通常与[Webview 透明](#webview-透明) 结合使用以制作冰霜效果的应用程序。 + +名称:WindowIsTranslucent
类型:`bool` + +#### Preferences + +The Preferences struct provides the ability to configure the Webview preferences. + +Name: Preferences
Type: [`*mac.Preferences`](#preferences-struct) + +##### Preferences struct + +You can specify the webview preferences. + +```go +type Preferences struct { + TabFocusesLinks u.Bool + TextInteractionEnabled u.Bool + FullscreenEnabled u.Bool +} +``` + +| 设置 | 描述 | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| TabFocusesLinks | A Boolean value that indicates whether pressing the tab key changes the focus to links and form controls. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/2818595-tabfocuseslinks?language=objc) | +| TextInteractionEnabled | A Boolean value that indicates whether to allow people to select or otherwise interact with text. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3727362-textinteractionenabled?language=objc) | +| FullscreenEnabled | A Boolean value that indicates whether a web view can display content full screen. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3917769-elementfullscreenenabled?language=objc) | + +示例: + +```go +Mac: &mac.Options{ + Preferences: &mac.Preferences{ + TabFocusesLinks: mac.Enabled, + TextInteractionEnabled: mac.Disabled, + FullscreenEnabled: mac.Enabled, + } +} +``` + +#### 关于 + +此配置允许您在“AppMenu”角色创建的应用程序菜单中设置“关于”菜单项的标题、消息和图标。 + +名称:About
类型:[`*mac.AboutInfo`](#关于结构体) + +##### 关于结构体 + +```go + +type AboutInfo struct { + Title string + Message string + Icon []byte +} +``` + +如果提供了这些设置,“关于”菜单项将出现在应用程序菜单中(使用`AppMenu` role 时)。 建议这样配置: + +```go +//go:embed build/appicon.png +var icon []byte + +func main() { + err := wails.Run(&options.App{ + ... + Mac: &mac.Options{ + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + }) + Mac: &mac.Options{ + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + }) + Mac: &mac.Options{ + About: &mac.AboutInfo{ + Title: "My Application", + Message: "© 2021 Me", + Icon: icon, + }, + }, + }) +``` + +“关于”菜单项将出现在应用程序菜单中: + +```mdx-code-block +
+ +
+
+``` + +单击后,将打开一个关于消息框: + +```mdx-code-block +
+ +
+
+``` + +### Linux + +这定义了 [Linux 特定的选项](#linux)。 + +名称:Linux
类型:`*linux.Options` + +#### 图标 + +设置代表窗口的图标。 当窗口最小化(也称为图标化)时使用此图标。 + +名称:Icon
类型:`[]byte` + +一些窗口管理器或桌面环境也可能将其放置在窗口框架中,或在其他上下文中显示。 在其他情况下,根本不使用该图标,因此您的预计情况可能会有所不同。 + +注意:Wayland 上的 Gnome 至少不显示此图标。 要在那里有一个应用程序图标,必须使用一个`.desktop`文件。 在 KDE 上它应该可以工作。 + +图标应该以自然绘制的任何尺寸提供;也就是说,在传递图像之前不要缩放图像。 缩放将延迟到当所需的最终尺寸已知的最后一刻,以获得最佳质量。 + +#### 窗口半透明 + +将此设置为 `true` 将使窗口半透明。 某些窗口管理员可能忽略它,或导致黑窗口。 + +名称:WindowIsTranslucent
类型:`bool` + +#### Webview GPU 策略 + +该选项用于决定 webview 的硬件加速策略。 + +名称:WebviewGpuPolicy
类型:[`options.WebviewGpuPolicy`](#webviewgpupolicy-type)
默认:`WebviewGpuPolicyAlways` + +##### Webview GPU 策略类型 + +| 值 | 描述 | +| ------------------------ | --------------------- | +| WebviewGpuPolicyAlways | 始终启用硬件加速 | +| WebviewGpuPolicyOnDemand | 根据 Web 内容的请求启用/禁用硬件加速 | +| WebviewGpuPolicyNever | 硬件加速始终处于禁用状态 | + +#### ProgramName + +This option is used to set the program's name for the window manager via GTK's g_set_prgname(). This name should not be localized, [see the docs](https://docs.gtk.org/glib/func.set_prgname.html). + +When a .desktop file is created this value helps with window grouping and desktop icons when the .desktop file's `Name` property differs form the executable's filename. + +Name: ProgramName
Type: string
+ +### 调试 + +这定义了用于调试构建的 [调试特定选项](#调试)。 + +名称: Debug
类型: `options.Debug` + +#### 启动时打开检查器 + +设置为 `true` 将在应用程序启动时打开 Web 检查器。 + +名称: OpenInspectorOnStartup
类型: `bool` + +[^1]: 这需要 WebKit2GTK 2.36+ 支持,并且您的应用程序需要使用构建标签 `webkit2_36` 来构建以激活对此功能的支持。 这也会将您应用程序的 WebKit2GTK 最低要求提高到 2.36。 +[^2]: 这需要 WebKit2GTK 2.40+ 支持,并且您的应用程序需要使用构建标签 `webkit2_40` 来构建以激活对此功能的支持。 这也将您的应用程序的 WebKit2GTK 最低要求提高到 2.40。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx new file mode 100644 index 00000000000..dc2a96b8a19 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/project-config.mdx @@ -0,0 +1,104 @@ +--- +sidebar_position: 5 +--- + +# 项目配置 + +项目配置在项目目录中的 `wails.json` 文件中。 配置的结构是: + +```json5 +{ + // 项目配置版本 + "version": "", + // 项目名称 + "name": "", + // 包含编译资产的目录的相对路径,这通常是推断的并且可以留空 + "assetdir": "", + // 触发重新加载的附加目录(逗号分隔),这仅用于某些高级资产配置 + "reloaddirs": "", + // 构建文件所在的目录。默认为“build” + "build:dir": "", + // 前端目录的相对路径。默认为“frontend” + "frontend:dir": "", + // 安装 Node 依赖的命令,在前端目录运行 - 通常是`npm install` + "frontend:install": "", + // 构建资产的命令,在前端目录中运行 - 通常是 `npm run build` + "frontend:build": "", + // 此命令已被 frontend:dev:build 取代。如果未指定 frontend:dev:build 将回退到此命令。 + // 如果此命令也未指定,将回退到 frontend:build + "frontend:dev": "", + // 此命令是 frontend:build 的 dev 等价物。 + // 如果未指定回退到 frontend:dev + "frontend:dev:build": "", + // 此命令是 frontend:install 的 dev 等价物。如果未指定回退到 frontend:install + "frontend:dev:install": "", + // 此命令在 `wails dev`上的单独进程中运行。用于第 3 方观察者或启动 3d 方开发服务器 + "frontend:dev:watcher": "", + // 用于服务资产的第 3 方开发服务器的 URL,比如 Vite。 + // 如果设置为 'auto' 那么 devServerUrl 将从 Vite 输出中推断出来 + "frontend:dev:serverUrl": "", + // 创建自动生成的 JS 模块的目录的相对路径 + "wailsjsdir": "", + // 二进制文件的名称 + "outputfilename": "", + // 开发服务器在检测到资产更改时等待重新加载的默认时间 + "debounceMS": 100, + // 将 wails 开发服务器绑定到的地址。默认为:localhost:34115 + "devServer": "", + // 在开发模式下以 shell 样式传递给应用程序的参数 + "appargs": "", + // 定义是否应该运行构建 Hooks,尽管它们是为主机操作系统以外的操作系统定义的。 + "runNonNativeBuildHooks": false, + // 构建前 Hooks + "preBuildHooks": { + // 在构建指定的 GOOS/GOARCH 之前将执行的命令:${platform} 被替换为“GOOS/GOARCH”。 + // “GOOS/GOARCH” hook 在“GOOS/*”和“*/*” hook 之前执行。 + "GOOS/GOARCH": "", + // 在指定 GOOS 的构建之前将执行的命令:${platform} 被替换为“GOOS/GOARCH”。 + // “GOOS/*” hook 在“*/*” hook 之前执行。 + "GOOS/*": "", + // 将在每次构建之前执行的命令:${platform} 替换为“GOOS/GOARCH”。 + "*/*": "" + }, + // 构建后 Hooks + "postBuildHooks": { + // 在构建指定的 GOOS/GOARCH 之后将执行的命令:${platform} 替换为“GOOS/GOARCH”, + // ${bin} 替换为已编译二进制文件的路径。 “GOOS/GOARCH” hook 在“GOOS/*”和“*/*” hook 之前执行。 + "GOOS/GOARCH": "", + // 在构建指定的 GOOS 之后将执行的命令:${platform} 替换为“GOOS/GOARCH”, + // ${bin} 替换为已编译二进制文件的路径。 “GOOS/*” hook 在“*/*” hook 之前执行。 + "GOOS/*": "", + // 每次构建后将执行的命令:${platform} 替换为“GOOS/GOARCH”, + // ${bin} 替换为已编译二进制文件的路径。 + "*/*": "" + }, + // 用于填充 manifest 和版本信息的数据。 + "info": { + // 公司名称。 默认值:[项目名] + "companyName": "", + // 产品名称。 默认值:[项目名] + "productName": "", + // 产品版本。默认值:'1.0.0' + "productVersion": "", + // 产品的版权。默认值:'Copyright.........' + "copyright": "", + // 该应用程序的简短评论。默认值:'Built using Wails (https://wails.app)' + "comments": "" + }, + // 'multiple': 每个架构一个安装程序。 + // 'single': 适用于正在构建的所有体系结构的单一通用安装程序。 + // 默认值:'multiple' + "nsisType": "", + // 应用程序是否应该被混淆。默认值:false + "obfuscated": "", + // 使用 obfuscated 标志时传递给乱码命令的参数 + "garbleargs": "" +} + +``` + +该文件将在运行 `wails build` 或 `wails dev` 时,由 Wails CLI 读取。 + +`wails build/dev` 命令中的 `assetdir`、`reloaddirs`、`wailsjsdir`、`debounceMS`、`devserver` 和 `frontenddevserverurl` 标志将覆盖项目配置并作为后续运行的默认值。 + +此文件的 `JSON Schema` 位于 [此处](https://wails.io/schemas/config.v2.json)。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/_category_.json b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/_category_.json new file mode 100644 index 00000000000..ac6d5548816 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Runtime", + "position": 1 +} diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx new file mode 100644 index 00000000000..0829be25f70 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/browser.mdx @@ -0,0 +1,13 @@ +--- +sidebar_position: 7 +--- + +# Browser 浏览器 + +这些方法与系统浏览器相关。 + +### BrowserOpenURL 浏览器打开 URL + +使用系统默认浏览器打开给定的 URL。 + +Go: `BrowserOpenURL(ctx context.Context, url string)`
JS: `BrowserOpenURL(url string)` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx new file mode 100644 index 00000000000..845dbc9f612 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/clipboard.mdx @@ -0,0 +1,23 @@ +--- +sidebar_position: 8 +--- + +# Clipboard 剪贴板 + +运行时的这一部分提供了对操作系统剪贴板的访问。
当前实现仅处理文本。 + +### ClipboardGetText 剪贴板获取文本 + +从剪切板读取当前存储的文本。 + +Go: `ClipboardGetText(ctx context.Context) (string, error)`
返回: 一个字符串(如果剪贴板为空,将返回一个空字符串)或一个错误。 + +JS: `ClipboardGetText(): Promise`
返回: 带有字符串结果的 Promise(如果剪贴板为空,将返回空字符串)。 + +### ClipboardSetText 剪贴板设置文本 + +将文本写入剪切板。 + +Go: `ClipboardSetText(ctx context.Context, text string) error`
返回: 如果存在错误,则会出现错误。 + +JS: `ClipboardSetText(text: string): Promise`
返回值: 一个Promise,如果文本成功地设置在剪贴板上,结果为 true,否则为 false。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx new file mode 100644 index 00000000000..7fd7f9640ae --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/dialog.mdx @@ -0,0 +1,302 @@ +--- +sidebar_position: 5 +--- + +# Dialog 对话框 + +运行时的这一部分提供对原生对话框的调用,例如文件选择器和消息框。 + +:::info JavaScript + +JS 运行时当前不支持对话框。 + +::: + +### OpenDirectoryDialog 打开选择目录对话框 + +打开一个对话框,提示用户选择目录。 可以使用 [ 打开选择文件对话框参数选项](#打开选择文件对话框参数选项) 进行自定义。 + +Go: `OpenDirectoryDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)` + +返回值: 所选目录(如果用户取消则为空白)或错误 + +### OpenFileDialog 打开选择文件对话框 + +打开一个对话框,提示用户选择文件。 可以使用 [ 打开选择文件对话框参数选项](#打开选择文件对话框参数选项) 进行自定义。 + +Go: `OpenFileDialog(ctx context.Context, dialogOptions OpenDialogOptions) (string, error)` + +返回值: 所选文件(如果用户取消则为空白)或错误 + +### OpenMultipleFilesDialog 打开选择多文件对话框 + +打开一个对话框,提示用户选择多个文件。 可以使用 [ 打开选择文件对话框参数选项](#打开选择文件对话框参数选项) 进行自定义。 + +Go: `OpenMultipleFilesDialog(ctx context.Context, dialogOptions OpenDialogOptions) ([]string, error)` + +返回值: 选定的文件(如果用户取消则为 nil)或错误 + +### SaveFileDialog 保存文件对话框 + +打开一个对话框,提示用户选择文件名以进行保存。 可以使用 [保存文件对话框参数选项](#保存文件对话框参数选项) 自定义。 + +Go: `SaveFileDialog(ctx context.Context, dialogOptions SaveDialogOptions) (string, error)` + +返回值: 所选文件(如果用户取消则为空白)或错误 + +### MessageDialog 消息对话框 + +使用消息对话框显示消息。 可以使用 [消息对话框参数选项](#消息对话框参数选项) 进行自定义。 + +Go: `MessageDialog(ctx context.Context, dialogOptions MessageDialogOptions) (string, error)` + +返回值: 所选按钮的文本或错误 + +## 参数选项 + +### 打开选择文件对话框参数选项 + +```go +type OpenDialogOptions struct { + DefaultDirectory string + DefaultFilename string + Title string + Filters []FileFilter + ShowHiddenFiles bool + CanCreateDirectories bool + ResolvesAliases bool + TreatPackagesAsDirectories bool +} +``` + +| 字段 | 描述 | Win | Mac | Lin | +| -------------------------- | ------------------- | --- | --- | --- | +| DefaultDirectory | 对话框打开时显示的目录 | ✅ | ✅ | ✅ | +| DefaultFilename | 默认文件名 | ✅ | ✅ | ✅ | +| Title | 对话框的标题 | ✅ | ✅ | ✅ | +| [Filters](#filefilter) | 文件过滤器列表 | ✅ | ✅ | ✅ | +| ShowHiddenFiles | 显示系统隐藏的文件 | | ✅ | ✅ | +| CanCreateDirectories | 允许用户创建目录 | | ✅ | | +| ResolvesAliases | 如果为 true,则返回文件而不是别名 | | ✅ | | +| TreatPackagesAsDirectories | 允许导航到包 | | ✅ | | + +### 保存文件对话框参数选项 + +```go +type SaveDialogOptions struct { + DefaultDirectory string + DefaultFilename string + Title string + Filters []FileFilter + ShowHiddenFiles bool + CanCreateDirectories bool + TreatPackagesAsDirectories bool +} +``` + +| 字段 | 描述 | Win | Mac | Lin | +| -------------------------- | ----------- | --- | --- | --- | +| DefaultDirectory | 对话框打开时显示的目录 | ✅ | ✅ | ✅ | +| DefaultFilename | 默认文件名 | ✅ | ✅ | ✅ | +| Title | 对话框的标题 | ✅ | ✅ | ✅ | +| [Filters](#filefilter) | 文件过滤器列表 | ✅ | ✅ | ✅ | +| ShowHiddenFiles | 显示系统隐藏的文件 | | ✅ | ✅ | +| CanCreateDirectories | 允许用户创建目录 | | ✅ | | +| TreatPackagesAsDirectories | 允许导航到包 | | ✅ | | + +### 消息对话框参数选项 + +```go +type MessageDialogOptions struct { + Type DialogType + Title string + Message string + Buttons []string + DefaultButton string + CancelButton string +} +``` + +| 字段 | 描述 | Win | Mac | Lin | +| ------------- | ------------------------------ | -------------- | --- | --- | +| 类型 | 消息对话框的类型,例如问题、信息... | ✅ | ✅ | ✅ | +| Title | 对话框的标题 | ✅ | ✅ | ✅ | +| Message | 向用户显示的消息 | ✅ | ✅ | ✅ | +| Buttons | 按钮标题列表 | | ✅ | | +| DefaultButton | 带有此文本的按钮应被视为默认按钮。 必定 `return`。 | ✅[*](#windows) | ✅ | | +| CancelButton | 带有此文本的按钮应被视为取消。 必定 `escape` | | ✅ | | + +#### Windows + +Windows 具有标准对话框类型,其中的按钮不可自定义。 返回的值将是以下之一:"Ok"、"Cancel"、"Abort"、"Retry"、"Ignore"、"Yes"、"No"、"Try Again"或"Continue"。 + +对于问题对话框,默认按钮是 “是”,取消按钮是 “否”。 可以通过将 `默认按钮` 值设置为 `"否"` 来改变这一点。 + +示例: +```go + result, err := runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{ + Type: runtime.QuestionDialog, + Title: "Question", + Message: "Do you want to continue?", + DefaultButton: "No", + }) +``` + +#### Linux + +Linux 有标准的对话框类型,其中的按钮是不可定制的。 返回的值将是以下之一:“Ok”、“Cancel”、“Yes”、“No” + +#### Mac + +Mac 上的消息对话框最多可以指定 4 个按钮。 如果没有 `DefaultButton` 或 `CancelButton` 给出,第一个按钮被认为是默认的并绑定到 `return` 键。 + +对于以下代码: + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, +}) +``` + +第一个按钮显示为默认值: + +```mdx-code-block +
+ +
+
+``` + +如果我们指定 `DefaultButton` 为“two”: + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, + DefaultButton: "two", +}) +``` + +第二个按钮显示为默认值。 当 `return` 被按下时,则返回数值“two”。 + +```mdx-code-block +
+ +
+
+``` + +如果我们现在指定`CancelButton`为“three”: + +```go +selection, err := runtime.MessageDialog(b.ctx, runtime.MessageDialogOptions{ + Title: "It's your turn!", + Message: "Select a number", + Buttons: []string{"one", "two", "three", "four"}, + DefaultButton: "two", + CancelButton: "three", +}) +``` + +带有“three”的按钮显示在对话框的底部。 当 `escape` 被按下时,则返回值“three”: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### 对话框类型 + +```go +const ( + InfoDialog DialogType = "info" + WarningDialog DialogType = "warning" + ErrorDialog DialogType = "error" + QuestionDialog DialogType = "question" + ) +``` + +### 文件过滤 + +```go +type FileFilter struct { + DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)" + Pattern string // semi-colon separated list of extensions, EG: "*.jpg;*.png" +} +``` + +#### Windows + +Windows 允许您在对话框中使用多个文件过滤器。 每个 FileFilter 将在对话框中显示为一个单独的条目: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### Linux + +Linux 允许您在对话框中使用多个文件过滤器。 每个 FileFilter 将在对话框中显示为一个单独的条目: + +```mdx-code-block +
+ +
+
+
+
+``` + +#### Mac + +Mac 对话框只有一组模式来过滤文件的概念。 如果提供了多个 FileFilters,Wails 将使用所有定义的模式。 + +示例: + +```go + selection, err := runtime.OpenFileDialog(b.ctx, runtime.OpenDialogOptions{ + Title: "Select File", + Filters: []runtime.FileFilter{ + { + DisplayName: "Images (*.png;*.jpg)", + Pattern: "*.png;*.jpg", + }, { + DisplayName: "Videos (*.mov;*.mp4)", + Pattern: "*.mov;*.mp4", + }, + }, + }) +``` + +这将导致使用 `*.png,*.jpg,*.mov,*.mp4` 作为过滤器打开文件对话框。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx new file mode 100644 index 00000000000..7788eed7b4c --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/events.mdx @@ -0,0 +1,37 @@ +--- +sidebar_position: 2 +--- + +# Events 事件 + +Wails 运行时提供了一个统一的事件系统,其中事件可以由 Go 或 JavaScript 发出或接收。 可选地,数据可以与事件一起传递。 侦听器将接收本地数据类型中的数据。 + +### EventsOn 添加事件侦听器 + +此方法为给定的事件名称设置一个侦听器。 当 [触发指定事件](#触发指定事件) 名为 `eventName` 类型的事件时,将触发回调。 与触发事件一起发送的任何其他数据都将传递给回调。 它返回 一个函数来取消侦听器。 + +Go: `EventsOn(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`
JS: `EventsOn(eventName string, callback function(optionalData?: any)): () => void` + +### EventsOff 移除事件侦听器 + +此方法取消注册给定事件名称的侦听器,可选地,可以通过 `additionalEventNames` 取消注册多个侦听器。 + +Go: `EventsOff(ctx context.Context, eventName string, additionalEventNames ...string)`
JS: `EventsOff(eventName string, ...additionalEventNames)` + +### EventsOnce 添加只触发一次的事件侦听器 + +此方法为给定的事件名称设置一个侦听器,但只会触发一次。 它返回 一个函数来取消侦听器。 + +Go: `EventsOnce(ctx context.Context, eventName string, callback func(optionalData ...interface{})) func()`
JS: `EventsOnce(eventName string, callback function(optionalData?: any)): () => void` + +### EventsOnMultiple 添加指定对多触发次数的事件侦听器 + +此方法为给定的事件名称设置一个侦听器,但最多只能触发 `counter` 次。 它返回 一个函数来取消侦听器。 + +Go: `EventsOnMultiple(ctx context.Context, eventName string, callback func(optionalData ...interface{}), counter int) func()`
JS: `EventsOnMultiple(eventName string, callback function(optionalData?: any), counter int): () => void` + +### EventsEmit 触发指定事件 + +此方法触发指定的事件。 可选数据可以与事件一起传递。 这将触发任意事件侦听器。 + +Go: `EventsEmit(ctx context.Context, eventName string, optionalData ...interface{})`
JS: `EventsEmit(eventName: string, ...optionalData: any)` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx new file mode 100644 index 00000000000..107e2def8e2 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/intro.mdx @@ -0,0 +1,85 @@ +--- +sidebar_position: 1 +--- + +# 简介 + +运行时是一个为应用程序提供实用方法的库。 有 Go 和 JavaScript 运行时,目的是在可能的情况下尝试使它们保持一致。 + +它具有以下实用方法: + +- [窗口](window.mdx) +- [菜单](menu.mdx) +- [对话框](dialog.mdx) +- [事件](events.mdx) +- [浏览器](browser.mdx) +- [日志](log.mdx) +- [剪切板](clipboard.mdx) + +Go 运行时可通过导入 `github.com/wailsapp/wails/v2/pkg/runtime` 获取。 此包中的所有方法都将 context 作为第一个参数。 此 context 应该从 [应用启动回调](../options.mdx#onstartup) 或 [前端 Dom 加载完成回调](../options.mdx#ondomready) 回调方法中获取。 + +:::info 注意 + +虽然上下文将提供给 [应用启动回调](../../reference/options#应用启动回调) 方法,但不能保证运行时将在此方法中工作,因为窗口正在不同的线程中初始化。 如果您希望在启动时调用运行时方法,请使用 [前端 Dom 加载完成回调](../../reference/options#前端-dom-加载完成回调) 方法。 + +::: + +JavaScript 库可通过 `window.runtime` 提供给前端。 使用 `开发` 模式时会生成一个运行时包,该包为运行时提供 TypeScript 声明。 这应该位于您的前端目录的`wailsjs`目录中。 + +### 隐藏 + +Go: `Hide(ctx context.Context)`
JS: `Hide()` + +隐藏应用程序。 + +:::info 注意 + +`Hide` 在 Mac 上,这将以与标准 Mac 应用程序中的菜单项相同的方式隐藏应用程序。 这与隐藏窗口不同,但应用程序仍处于前台。 对于 Windows 和 Linux,这与 `WindowHide` 相同。 + +::: + +### 显示 + +显示应用程序。 + +:::info 注意 + +在 Mac 上,这会将应用程序带回前台。 对于 Windows 和 Linux,这目前与 `WindowShow` 相同。 + +::: + +Go: `Show(ctx context.Context)`
JS: `Show()` + +### 退出 + +退出应用程序。 + +Go: `Quit(ctx context.Context)`
JS: `Quit()` + +### 环境 + +返回当前环境的详细信息。 + +Go: `Environment(ctx context.Context) EnvironmentInfo`
JS: `Environment(): Promise` + +#### 环境信息 + +Go: + +```go +type EnvironmentInfo struct { + BuildType string + Platform string + Arch string +} +``` + +JS: + +```ts +interface EnvironmentInfo { + buildType: string; + platform: string; + arch: string; +} +``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx new file mode 100644 index 00000000000..d109faab2ee --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/log.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 3 +--- + +# Log 日志 + +Wails 运行时提供了一种可以从 Go 或 JavaScript 调用日志记录的机制。 像大多数记录器一样,有许多日志级别: + +- Trace(追踪) +- Debug(调试) +- Info(信息) +- Warning(警告) +- Error(错误) +- Fatal(致命) + +记录器将输出当前或更高日志级别的任何日志消息。 示例:`Debug`日志级别将输出除`Trace`消息之外的所有消息。 + +### LogPrint Print 日志 + +将给定的消息记录为原始消息。 + +Go: `LogPrint(ctx context.Context, message string)`
JS: `LogPrint(message: string)` + +### LogPrintf 格式化 Print 日志 + +将给定的消息记录为原始消息。 + +Go: `LogPrintf(ctx context.Context, format string, args ...interface{})`
+ +### LogTrace Trace 日志 + +在 `Trace` 日志级别记录给定的消息。 + +Go: `LogTrace(ctx context.Context, message string)`
JS: `LogTrace(message: string)` + +### LogTracef 格式化 Trace 日志 + +在 `Trace` 日志级别记录给定的消息。 + +Go: `LogTracef(ctx context.Context, format string, args ...interface{})`
+ +### LogDebug Debug 日志 + +在 `Debug` 日志级别记录给定的消息。 + +Go: `LogDebug(ctx context.Context, message string)`
JS: `LogDebug(message: string)` + +### LogDebugf 格式化 Debug 日志 + +在 `Debug` 日志级别记录给定的消息。 + +Go: `LogDebugf(ctx context.Context, format string, args ...interface{})`
+ +### LogInfo Info 日志 + +在`Info`日志级别记录给定的消息。 + +Go: `LogInfo(ctx context.Context, message string)`
JS: `LogInfo(message: string)` + +### LogInfof 格式化 Info 日志 + +在`Info`日志级别记录给定的消息。 + +Go: `LogInfof(ctx context.Context, format string, args ...interface{})`
+ +### LogWarning Warning 日志 + +在 `Warning` 日志级别记录给定的消息。 + +Go: `LogWarning(ctx context.Context, message string)`
JS: `LogWarning(message: string)` + +### LogWarningf 格式化 Warning 日志 + +在 `Warning` 日志级别记录给定的消息。 + +Go: `LogWarningf(ctx context.Context, format string, args ...interface{})`
+ +### LogError Error 日志 + +在 `Error` 日志级别记录给定的消息。 + +Go: `LogError(ctx context.Context, message string)`
JS: `LogError(message: string)` + +### LogErrorf 格式化 Error 日志 + +在 `Error` 日志级别记录给定的消息。 + +Go: `LogErrorf(ctx context.Context, format string, args ...interface{})`
+ +### LogFatal Fatal 日志 + +在 `Fatal` 日志级别记录给定的消息。 + +Go: `LogFatal(ctx context.Context, message string)`
JS: `LogFatal(message: string)` + +### LogFatalf 格式化 Fatal 日志 + +在 `Fatal` 日志级别记录给定的消息。 + +Go: `LogFatalf(ctx context.Context, format string, args ...interface{})`
+ +### LogSetLogLevel 设置日志级别 + +设置日志级别。 在 JavaScript 中,该数字与以下日志级别有关: + +| 值 | 日志等级 | +| - | ----------- | +| 1 | Trace(追踪) | +| 2 | Debug(调试) | +| 3 | Info(信息) | +| 4 | Warning(警告) | +| 5 | Error(错误) | + +Go: `LogSetLogLevel(ctx context.Context, level logger.LogLevel)`
JS: `LogSetLogLevel(level: number)` + +## 使用自定义日志 + +可以通过使用应用程序参数选项 [日志](../../reference/options#日志) 提供自定义记录器来使用它。 唯一的要求是记录器实现在 `github.com/wailsapp/wails/v2/pkg/logger` 里 `logger.Logger` 定义的接口: + +```go title="logger.go" +type Logger interface { + Print(message string) + Trace(message string) + Debug(message string) + Info(message string) + Warning(message string) + Error(message string) + Fatal(message string) +} +``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx new file mode 100644 index 00000000000..9d176d06a61 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/menu.mdx @@ -0,0 +1,25 @@ +--- +sidebar_position: 6 +--- + +# Menu 菜单 + +这些方法与应用程序菜单相关。 + +:::info JavaScript + +JS 运行时当前不支持菜单。 + +::: + +### MenuSetApplicationMenu 设置应用程序菜单 + +将应用程序菜单设置为给定的 [菜单](../menus.mdx)。 + +Go: `MenuSetApplicationMenu(ctx context.Context, menu *menu.Menu)` + +### MenuUpdateApplicationMenu 更新应用程序菜单 + +获取传递给 `MenuSetApplicationMenu` 的菜单的任意更改更新应用程序菜单。 + +Go: `MenuUpdateApplicationMenu(ctx context.Context)` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx new file mode 100644 index 00000000000..457c92ebff9 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/screen.mdx @@ -0,0 +1,38 @@ +--- +sidebar_position: 9 +--- + +# Screen + +These methods provide information about the currently connected screens. + +### ScreenGetAll + +Returns a list of currently connected screens. + +Go: `ScreenGetAll(ctx context.Context) []screen`
+JS: `ScreenGetAll()` + +#### Screen + +Go struct: + +```go +type Screen struct { + IsCurrent bool + IsPrimary bool + Width int + Height int +} +``` + +Typescript interface: + +```ts +interface Screen { + isCurrent: boolean; + isPrimary: boolean; + width : number + height : number +} +``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx new file mode 100644 index 00000000000..a4b9c1263b5 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/reference/runtime/window.mdx @@ -0,0 +1,227 @@ +--- +sidebar_position: 4 +--- + +# Window 窗口 + +这些方法可以控制应用程序窗口。 + +### WindowSetTitle 窗口标题 + +设置窗口标题栏中的文本。 + +Go: `WindowSetTitle(ctx context.Context, title string)`
JS: `WindowSetTitle(title: string)` + +### WindowFullscreen 窗口全屏 + +使窗口全屏。 + +Go: `WindowFullscreen(ctx context.Context)`
JS: `WindowFullscreen()` + +### WindowUnfullscreen 窗口取消全屏 + +恢复全屏之前的先前窗口尺寸和位置。 + +Go: `WindowUnfullscreen(ctx context.Context)`
JS: `WindowUnfullscreen()` + +### WindowIsFullscreen 窗口是否全屏 + +如果窗口是全屏的,则返回 true。 + +Go: `WindowIsFullscreen(ctx context.Context) bool`
JS: `WindowIsFullscreen() bool` + +### WindowCenter 窗口居中 + +使窗口在当前窗口所在的监视器上居中。 + +Go: `WindowCenter(ctx context.Context)`
JS: `WindowCenter()` + +### WindowExecJS 窗口执行JS代码 + +在窗口中执行任意 JS 代码。 + +此方法在浏览器中异步运行代码并立即返回。 如果脚本导致任何错误,它们将只在浏览器控制台中可用。 + +Go: `WindowExecJS(ctx context.Context, js string)` + +### WindowReload 窗口重新加载 + +执行“重新加载”(重新加载当前页面)。 + +Go: `WindowReload(ctx context.Context)`
JS: `WindowReload()` + +### WindowReloadApp 重新加载应用程序前端。 + +重新加载应用程序前端。 + +Go: `WindowReloadApp(ctx context.Context)`
JS: `WindowReloadApp()` + +### WindowSetSystemDefaultTheme 窗口设置系统默认主题 + +仅限 Windows。 + +Go: `WindowSetSystemDefaultTheme(ctx context.Context)`
JS: `WindowSetSystemDefaultTheme()` + +将窗口主题设置为系统默认值(暗/亮)。 + +### WindowSetLightTheme 窗口设置浅色主题 + +仅限 Windows。 + +Go: `WindowSetLightTheme(ctx context.Context)`
JS: `WindowSetLightTheme()` + +将窗口主题设置为浅色。 + +### WindowSetDarkTheme 窗口设置深色主题 + +仅限 Windows。 + +Go: `WindowSetDarkTheme(ctx context.Context)`
JS: `WindowSetDarkTheme()` + +将窗口主题设置为深色。 + +### WindowShow 显示窗口 + +显示窗口,如果它当前是隐藏的。 + +Go: `WindowShow(ctx context.Context)`
JS: `WindowShow()` + +### WindowShow 隐藏窗口 + +如果当前可见,则隐藏窗口。 + +Go: `WindowHide(ctx context.Context)`
JS: `WindowHide()` + +### WindowIsNormal 窗口是否为正常 + +如果窗口未最小化、最大化或全屏,则返回 true。 + +Go: `WindowIsNormal(ctx context.Context) bool`
JS: `WindowIsNormal() bool` + +### WindowSetSize 设置窗口尺寸 + +设置窗口的宽度和高度。 + +Go: `WindowSetSize(ctx context.Context, width int, height int)`
JS: `WindowSetSize(width: number, height: number)` + +### WindowGetSize 获取窗口尺寸 + +获取窗口的宽度和高度。 + +Go: `WindowGetSize(ctx context.Context) (width int, height int)`
JS: `WindowGetSize() : Size` + +### WindowSetMinSize 设置窗口最小尺寸 + +设置窗口最小尺寸。 如果窗口当前小于给定尺寸,将调整窗口大小。 + +设置大小 `0,0` 将禁用此约束。 + +Go: `WindowSetMinSize(ctx context.Context, width int, height int)`
JS: `WindowSetMinSize(width: number, height: number)` + +### WindowSetMaxSize 设置窗口最大尺寸 + +设置窗口最大尺寸。 如果窗口当前大于给定尺寸,将调整窗口大小。 + +设置大小 `0,0` 将禁用此约束。 + +Go: `WindowSetMaxSize(ctx context.Context, width int, height int)`
JS: `WindowSetMaxSize(width: number, height: number)` + +### WindowSetAlwaysOnTop 设置窗口置顶 + +设置窗口置顶或取消置顶。 + +Go: `WindowSetAlwaysOnTop(ctx context.Context, b bool)`
JS: `WindowSetAlwaysOnTop(b: Boolen)` + +### WindowSetPosition 设置窗口位置 + +设置相对于窗口当前所在监视器的窗口位置。 + +Go: `WindowSetPosition(ctx context.Context, x int, y int)`
JS: `WindowSetPosition(x: number, y: number)` + +### WindowGetPosition 获取窗口位置 + +获取相对于窗口当前所在监视器的窗口位置。 + +Go: `WindowGetPosition(ctx context.Context) (x int, y int)`
JS: `WindowGetPosition() : Position` + +### WindowMaximise 窗口最大化 + +最大化窗口以填满屏幕。 + +Go: `WindowMaximise(ctx context.Context)`
JS: `WindowMaximise()` + +### WindowUnmaximise 窗口取消最大化 + +将窗口恢复到最大化之前的尺寸和位置。 + +Go: `WindowUnmaximise(ctx context.Context)`
JS: `WindowUnmaximise()` + +### WindowIsMaximised 窗口是否最大化 + +如果窗口最大化,则返回 true。 + +Go: `WindowIsMaximised(ctx context.Context) bool`
JS: `WindowIsMaximised() bool` + +### WindowToggleMaximise 窗口最大化切换 + +在最大化和未最大化之间切换。 + +Go: `WindowToggleMaximise(ctx context.Context)`
JS: `WindowToggleMaximise()` + +### WindowMinimise 窗口最小化。 + +最小化窗口。 + +Go: `WindowMinimise(ctx context.Context)`
JS: `WindowMinimise()` + +### WindowUnminimise 窗口取消最小化 + +将窗口恢复到最小化之前的尺寸和位置。 + +Go: `WindowUnminimise(ctx context.Context)`
JS: `WindowUnminimise()` + +### WindowIsMinimised 窗口是否最小化 + +如果窗口最小化,则返回 true。 + +Go: `WindowIsMinimised(ctx context.Context) bool`
JS: `WindowIsMinimised() bool` + +### WindowSetBackgroundColour 窗口设置背景色 + +将窗口的背景颜色设置为给定的 RGBA 颜色定义。 这种颜色将显示所有透明像素。 + +R、G、B 和 A 的有效值为 0-255。 + +:::info Windows + +在 Windows 上,仅支持 0 或 255 的 alpha 值。 任何非 0 的值都将被视为 255。 + +::: + +Go: `WindowSetBackgroundColour(ctx context.Context, R, G, B, A uint8)`
JS: `WindowSetBackgroundColour(R, G, B, A)` + +### WindowPrint + +Opens tha native print dialog. + +Go: `WindowPrint(ctx context.Context)`
JS: `WindowPrint()` + +## TypeScript 对象定义 + +### Position(位置) + +```ts +interface Position { + x: number; + y: number; +} +``` + +### Size(尺寸) + +```ts +interface Size { + w: number; + h: number; +} +``` diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/_category_.json b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/_category_.json new file mode 100644 index 00000000000..dfac1d175e6 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Tutorials", + "position": 70 +} diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx new file mode 100644 index 00000000000..cb5d4d79ce6 --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/dogsapi.mdx @@ -0,0 +1,245 @@ +--- +sidebar_position: 20 +--- + +# 狗狗 API + +```mdx-code-block +
+ +
+
+``` + +:::note + +本教程由 [@tatadan](https://twitter.com/tatadan) 友情提供,是他们的 [Wails Examples Repository](https://github.com/tataDan/wails-v2-examples) 的一部分。 + +::: + +在本教程中,我们将开发一个应用程序,从网络上检索狗的照片,然后显示它们。 + +### 创建项目 + +让我们创建应用程序。 从终端输入:`wails init -n dogs-api -t svelte` + +注意:如果您想添加 IDE 支持,我们可以选择在此命令的末尾添加 `-ide vscode` 或 `-ide goland`。 + +现在让我们 `cd dogs-api` 开始编辑项目文件。 + +### 删除未使用的代码 + +我们将从删除一些我们知道不会使用的元素开始: + +- 打开 `app.go` 并删除以下行: + +```go +// Greet returns a greeting for the given name +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s, It's show time!", name) +} +``` + +- 打开 `frontend/src/App.svelte` 并删除所有行。 +- 删除 `frontend/src/assets/images/logo-universal.png` 文件 + +### 创建应用程序 + +现在让我们添加新的 Go 代码。 + +在函数定义之前添加以下结构声明到 `app.go`: + +```go +type RandomImage struct { + Message string + Status string +} + +type AllBreeds struct { + Message map[string]map[string][]string + Status string +} + +type ImagesByBreed struct { + Message []string + Status string +} +``` + +将以下函数添加到 `app.go`(可能在现有函数定义之后): + +```go +func (a *App) GetRandomImageUrl() string { + response, err := http.Get("https://dog.ceo/api/breeds/image/random") + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data RandomImage + json.Unmarshal(responseData, &data) + + return data.Message +} + +func (a *App) GetBreedList() []string { + var breeds []string + + response, err := http.Get("https://dog.ceo/api/breeds/list/all") + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data AllBreeds + json.Unmarshal(responseData, &data) + + for k := range data.Message { + breeds = append(breeds, k) + } + + sort.Strings(breeds) + + return breeds +} + +func (a *App) GetImageUrlsByBreed(breed string) []string { + + url := fmt.Sprintf("%s%s%s%s", "https://dog.ceo/api/", "breed/", breed, "/images") + response, err := http.Get(url) + if err != nil { + log.Fatal(err) + } + + responseData, err := ioutil.ReadAll(response.Body) + if err != nil { + log.Fatal(err) + } + + var data ImagesByBreed + json.Unmarshal(responseData, &data) + + return data.Message +} +``` + +将 `app.go` 的 `import` 部分修改为如下所示: + +```go +import ( + "context" + "fmt" + "encoding/json" + "io/ioutil" + "log" + "net/http" + "sort" +) +``` + +将以下行添加到 `frontend/src/App.svelte`: + + +```html + + +

Dogs API

+
+ + Click on down arrow to select a breed + + +
+
+{#if showRandomPhoto} + No dog found +{/if} +{#if showBreedPhotos} + {#each photos as photo} + No dog found + {/each} +{/if} + + +``` + + +### 创建应用程序 + +要生成绑定并测试应用程序,请运行 `wails dev`。 + +### 编译应用程序 + +要将应用程序编译为单个可用于生产的二进制文件,请运行 `wails build`。 diff --git a/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx new file mode 100644 index 00000000000..863f7ac8f0a --- /dev/null +++ b/website/i18n/zh-Hans/docusaurus-plugin-content-docs/version-v2.8.0/tutorials/helloworld.mdx @@ -0,0 +1,123 @@ +--- +sidebar_position: 10 +--- + +# 你好世界 + +本教程的目的是让您使用 Wails 启动并运行最基本的应用程序。 你将可以: + +- 创建一个新的 Wails 应用 +- 构建应用 +- 运行应用 + +:::note + +本教程使用 Windows 作为目标平台。 根据您的操作系统,输出会略有不同。 + +::: + +## 创建一个新的 Wails 应用 + +使用默认的 vanilla JS 模板创建新的 Wails 程序, 您需要运行这个指令: + +```bash +wails init -n helloworld +``` + +您应该会看到如下输出: + +``` +Wails CLI v2.0.0 + +Initialising Project 'helloworld' +--------------------------------- + +Project Name: helloworld +Project Directory: C:\Users\leaan\tutorial\helloworld +Project Template: vanilla +Template Support: https://wails.io + +Initialised project 'helloworld' in 232ms. +``` + +这将在当前目录中创建一个名为 `helloworld` 的新目录。 在此目录中,您将找到许多文件: + +``` +build/ - Contains the build files + compiled application +frontend/ - Contains the frontend files +app.go - Contains the application code +main.go - The main program with the application configuration +wails.json - The project configuration file +go.mod - The go module file +go.sum - The go module checksum file +``` + +## 构建应用 + +要构建应用程序,请切换到新的 `helloword` 项目目录并运行以下命令: + +```bash +wails build +``` + +您应该会看到如下输出: + +``` +Wails CLI v2.0.0 + +App Type: desktop +Platforms: windows/amd64 +Compiler: C:\Users\leaan\go\go1.18.3\bin\go.exe +Build Mode: Production +Devtools: false +Skip Frontend: false +Compress: false +Package: true +Clean Build Dir: false +LDFlags: "" +Tags: [] +Race Detector: false + +Building target: windows/amd64 +------------------------------ + - Installing frontend dependencies: Done. + - Compiling frontend: Done. + - Generating bundle assets: Done. + - Compiling application: Done. +Built 'C:\Users\leaan\tutorial\helloworld\build\bin\helloworld.exe' in 10.616s. +``` + +这已经编译了应用程序并将其保存在 `build/bin` 目录中。 + +## 运行应用 + +如果我们在 Windows 文件管理器中查看 `build/bin` 目录,我们应该看到我们的项目二进制文件: + +```mdx-code-block +
+ +
+
+``` + +我们可以通过简单的双击 `helloworld.exe` 文件来运行它。 + +在 Mac 上,Wails 生成一个 `helloworld.app` 文件,可以通过双击来运行。 + +在 Linux 上,您可以从 `build/bin` 目录使用 `./helloword` 运行应用程序。 + +您应该看到应用程序正常工作: + +```mdx-code-block +
+ +
+
+``` diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index 42baf728adc..2a2ebeaf778 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## v2.8.0 - 2024-02-08 + ### Added - Added option to specify platform for dev command. Thanks to [@pylotlight](https://github.com/pylotlight) for the fix ([#3117](https://github.com/wailsapp/wails/pull/3117)). Based on the work of [@evsign](https://github.com/evsign) in [Draft PR](https://github.com/wailsapp/wails/pull/2724). - Added windows options supports `DisablePinchZoom` configuration. Added by @tuuzed in [PR](https://github.com/wailsapp/wails/pull/3115) diff --git a/website/versioned_docs/version-v2.8.0/appendix/_category_.json b/website/versioned_docs/version-v2.8.0/appendix/_category_.json new file mode 100644 index 00000000000..83af4ca28fd --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/appendix/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Appendix", + "position": 70 +} diff --git a/website/versioned_docs/version-v2.8.0/community/_category_.json b/website/versioned_docs/version-v2.8.0/community/_category_.json new file mode 100644 index 00000000000..524986e1e49 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Community", + "position": 50 +} diff --git a/website/versioned_docs/version-v2.6.0/community/links.mdx b/website/versioned_docs/version-v2.8.0/community/links.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/links.mdx rename to website/versioned_docs/version-v2.8.0/community/links.mdx diff --git a/website/versioned_docs/version-v2.8.0/community/showcase/_category_.json b/website/versioned_docs/version-v2.8.0/community/showcase/_category_.json new file mode 100644 index 00000000000..276e283b71f --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/showcase/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Showcase", + "position": 1 +} diff --git a/website/versioned_docs/version-v2.8.0/community/showcase/bulletinboard.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/bulletinboard.mdx new file mode 100644 index 00000000000..37be75135ed --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/showcase/bulletinboard.mdx @@ -0,0 +1,10 @@ +# BulletinBoard + +```mdx-code-block +

+ +
+

+``` + +The [BulletinBoard](https://github.com/raguay/BulletinBoard) application is a versital message board for static messages or dialogs to get information from the user for a script. It has a TUI for creating new dialogs that can latter be used to get information from the user. It's design is to stay running on your system and show the information as needed and then hide away. I have a process for watching a file on my system and sending the contents to BulletinBoard when changed. It works great with my workflows. There is also an [Alfred workflow](https://github.com/raguay/MyAlfred/blob/master/Alfred%205/EmailIt.alfredworkflow) for sending information to the program. The workflow is also for working with [EmailIt](https://github.com/raguay/EmailIt). diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/cfntracker.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/cfntracker.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/cfntracker.mdx rename to website/versioned_docs/version-v2.8.0/community/showcase/cfntracker.mdx diff --git a/website/versioned_docs/version-v2.8.0/community/showcase/emailit.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/emailit.mdx new file mode 100644 index 00000000000..c1817b70fff --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/showcase/emailit.mdx @@ -0,0 +1,10 @@ +# EmailIt + +```mdx-code-block +

+ +
+

+``` + +[EmailIt](https://github.com/raguay/EmailIt/) is a Wails 2 program that is a markdown based email sender only with nine notepads, scripts to manipulate the text, and templates. It also has a scripts terminal to run scripts in EmailIt on files in your system. The scripts and templates can be used from the commandline itself or with the Alfred, Keyboard Maestro, Dropzone, or PopClip extensions. It also supports scripts and themes downloaded form GitHub. Documentation is not complete, but the programs works. It’s built using Wails2 and Svelte, and the download is a universal macOS application. diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/encrypteasy.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/encrypteasy.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/encrypteasy.mdx rename to website/versioned_docs/version-v2.8.0/community/showcase/encrypteasy.mdx diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/espstudio.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/espstudio.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/espstudio.mdx rename to website/versioned_docs/version-v2.8.0/community/showcase/espstudio.mdx diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/filehound.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/filehound.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/filehound.mdx rename to website/versioned_docs/version-v2.8.0/community/showcase/filehound.mdx diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/hiposter.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/hiposter.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/hiposter.mdx rename to website/versioned_docs/version-v2.8.0/community/showcase/hiposter.mdx diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/minecraftupdater.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/minecraftupdater.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/minecraftupdater.mdx rename to website/versioned_docs/version-v2.8.0/community/showcase/minecraftupdater.mdx diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/modalfilemanager.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/modalfilemanager.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/modalfilemanager.mdx rename to website/versioned_docs/version-v2.8.0/community/showcase/modalfilemanager.mdx diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/mollywallet.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/mollywallet.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/mollywallet.mdx rename to website/versioned_docs/version-v2.8.0/community/showcase/mollywallet.mdx diff --git a/website/versioned_docs/version-v2.8.0/community/showcase/october.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/october.mdx new file mode 100644 index 00000000000..66d634dc519 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/showcase/october.mdx @@ -0,0 +1,14 @@ +# October + +```mdx-code-block +

+ +
+

+``` + +[October](https://october.utf9k.net) is a small Wails application that makes it really easy to extract highlights from [Kobo eReaders](https://en.wikipedia.org/wiki/Kobo_eReader) and then forward them to [Readwise](https://readwise.io). + +It has a relatively small scope with all platform versions weighing in under 10MB, and that's without enabling [UPX compression](https://upx.github.io/)! + +In contrast, the author's previous attempts with Electron quickly bloated to several hundred megabytes. diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/optimus.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/optimus.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/optimus.mdx rename to website/versioned_docs/version-v2.8.0/community/showcase/optimus.mdx diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/portfall.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/portfall.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/portfall.mdx rename to website/versioned_docs/version-v2.8.0/community/showcase/portfall.mdx diff --git a/website/versioned_docs/version-v2.8.0/community/showcase/restic-browser.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/restic-browser.mdx new file mode 100644 index 00000000000..3646384ecad --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/showcase/restic-browser.mdx @@ -0,0 +1,12 @@ +# Restic Browser + +```mdx-code-block +

+ +
+

+``` + +[Restic-Browser](https://github.com/emuell/restic-browser) - A simple, cross-platform [restic](https://github.com/restic/restic) backup GUI for browsing and restoring restic repositories. diff --git a/website/versioned_docs/version-v2.8.0/community/showcase/riftshare.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/riftshare.mdx new file mode 100644 index 00000000000..9928b478576 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/showcase/riftshare.mdx @@ -0,0 +1,21 @@ +# RiftShare + +```mdx-code-block +

+ +
+

+``` + +Easy, Secure, and Free file sharing for everyone. Learn more at [Riftshare.app](https://riftshare.app) + +## Features + +- Easy secure file sharing between computers both in the local network and through the internet +- Supports sending files or directories securely through the [magic wormhole protocol](https://magic-wormhole.readthedocs.io/en/latest/) +- Compatible with all other apps using magic wormhole (magic-wormhole or wormhole-william CLI, wormhole-gui, etc.) +- Automatic zipping of multiple selected files to send at once +- Full animations, progress bar, and cancellation support for sending and receiving +- Native OS File Selection +- Open files in one click once received +- Auto Update - don't worry about having the latest release! diff --git a/website/versioned_docs/version-v2.8.0/community/showcase/scriptbar.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/scriptbar.mdx new file mode 100644 index 00000000000..3e41eb32abf --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/showcase/scriptbar.mdx @@ -0,0 +1,10 @@ +# ScriptBar + +```mdx-code-block +

+ +
+

+``` + +[ScriptBar](https://GitHub.com/raguay/ScriptBarApp) is a program to show the output of scripts or [Node-Red](https://nodered.org) server. It runs scripts defined in EmailIt program and shows the output. Scripts from xBar or TextBar can be used, but currently on the TextBar scripts work well. It also displays the output of scripts on your system. ScriptBar doesn't put them in the menubar, but has them all in a convient window for easy viewing. You can have multiple tabs to have many different things show. You can also keep the links to your most visited web sites. diff --git a/website/versioned_docs/version-v2.8.0/community/showcase/snippetexpander.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/snippetexpander.mdx new file mode 100644 index 00000000000..1f9fb615796 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/showcase/snippetexpander.mdx @@ -0,0 +1,27 @@ +# Snippet Expander + +```mdx-code-block +

+ +
+ Screenshot of Snippet Expander's Select Snippet window +

+

+ +
+ Screenshot of Snippet Expander's Add Snippet screen +

+

+ +
+ Screenshot of Snippet Expander's Search & Paste window +

+``` + +[Snippet Expander](https://snippetexpander.org) is "Your little expandable text snippets helper", for Linux. + +Snippet Expander comprises of a GUI application built with Wails for managing snippets and settings, with a Search & Paste window mode for quickly selecting and pasting a snippet. + +The Wails based GUI, go-lang CLI and vala-lang auto expander daemon all communicate with a go-lang daemon via D-Bus. The daemon does the majority of the work, managing the database of snippets and common settings, and providing services for expanding and pasting snippets etc. + +Check out the [source code](https://git.sr.ht/~ianmjones/snippetexpander/tree/trunk/item/cmd/snippetexpandergui/app.go#L38) to see how the Wails app sends messages from the UI to the backend that are then sent to the daemon, and subscribes to a D-Bus event to monitor changes to snippets via another instance of the app or CLI and show them instantly in the UI via a Wails event. diff --git a/website/versioned_docs/version-v2.8.0/community/showcase/surge.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/surge.mdx new file mode 100644 index 00000000000..c3b3fb4c06d --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/showcase/surge.mdx @@ -0,0 +1,10 @@ +# Surge + +```mdx-code-block +

+ +
+

+``` + +[Surge](https://getsurge.io/) is a p2p filesharing app designed to utilize blockchain technologies to enable 100% anonymous file transfers. Surge is end-to-end encrypted, decentralized and open source. diff --git a/website/versioned_docs/version-v2.8.0/community/showcase/tinyrdm.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/tinyrdm.mdx new file mode 100644 index 00000000000..e3124bab727 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/showcase/tinyrdm.mdx @@ -0,0 +1,11 @@ +# Tiny RDM + +```mdx-code-block +

+ + +
+

+``` + +The [Tiny RDM](https://redis.tinycraft.cc/) application is an open-source, modern lightweight Redis GUI. It has a beautful UI, intuitive Redis database management, and compatible with Windows, Mac, and Linux. It provides visual key-value data operations, supports various data decoding and viewing options, built-in console for executing commands, slow log queries and more. diff --git a/website/versioned_docs/version-v2.8.0/community/showcase/wally.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/wally.mdx new file mode 100644 index 00000000000..7408aa5854f --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/showcase/wally.mdx @@ -0,0 +1,10 @@ +# Wally + +```mdx-code-block +

+ +
+

+``` + +[Wally](https://ergodox-ez.com/pages/wally) is the official firmware flasher for [Ergodox](https://ergodox-ez.com/) keyboards. It looks great and is a fantastic example of what you can achieve with Wails: the ability to combine the power of Go and the rich graphical tools of the web development world. diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/warmine.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/warmine.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/warmine.mdx rename to website/versioned_docs/version-v2.8.0/community/showcase/warmine.mdx diff --git a/website/versioned_docs/version-v2.6.0/community/showcase/wombat.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/wombat.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/community/showcase/wombat.mdx rename to website/versioned_docs/version-v2.8.0/community/showcase/wombat.mdx diff --git a/website/versioned_docs/version-v2.8.0/community/showcase/ytd.mdx b/website/versioned_docs/version-v2.8.0/community/showcase/ytd.mdx new file mode 100644 index 00000000000..5db428f722c --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/community/showcase/ytd.mdx @@ -0,0 +1,10 @@ +# Ytd + +```mdx-code-block +

+ +
+

+``` + +[Ytd](https://github.com/marcio199226/ytd/tree/v2-wails) is an app for downloading tracks from youtube, creating offline playlists and share them with your friends, your friends will be able to playback your playlists or download them for offline listening, has an built-in player. diff --git a/website/versioned_docs/version-v2.6.0/community/templates.mdx b/website/versioned_docs/version-v2.8.0/community/templates.mdx similarity index 92% rename from website/versioned_docs/version-v2.6.0/community/templates.mdx rename to website/versioned_docs/version-v2.8.0/community/templates.mdx index c25af548eaf..98726c60aff 100644 --- a/website/versioned_docs/version-v2.6.0/community/templates.mdx +++ b/website/versioned_docs/version-v2.8.0/community/templates.mdx @@ -29,7 +29,6 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for - [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - A template using JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier) - [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - A template using TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier, Composition API with <script setup>) - [wails-template-naive](https://github.com/tk103331/wails-template-naive) - Wails template based on Naive UI (A Vue 3 Component Library) -- [wails-vite-vue-ts-navie-pinia](https://github.com/id88/wails-vite-vue-ts-navie-pinia) - A template for Wails with Vite + Vue + TypeScript + NavieUI + Pinia ## Angular @@ -41,9 +40,9 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for - [wails-react-template](https://github.com/AlienRecall/wails-react-template) - A template using reactjs - [wails-react-template](https://github.com/flin7/wails-react-template) - A minimal template for React that supports live development - [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - A template using Next.js and TypeScript +- [wails-template-nextjs-app-router](https://github.com/thisisvk-in/wails-template-nextjs-app-router) - A template using Next.js and TypeScript with App router - [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - A template for React + TypeScript + Vite + TailwindCSS - [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - A template with Vite, React, TypeScript, TailwindCSS, and shadcn/ui -- [wails-vite-react](https://github.com/vixalie/wails-vite-react) - A minimal template for React, using Vite for assets building ## Svelte @@ -63,6 +62,10 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for - [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - Develop your GUI app with functional programming and a **snappy** hot-reload setup :tada: :rocket: - [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - Combine the powers :muscle: of Elm + Tailwind CSS + Wails! Hot reloading supported. +## HTMX + +- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - Use a unique combination of pure htmx for interactivity plus templ for creating components and forms + ## Pure JavaScript (Vanilla) - [wails-pure-js-template](https://github.com/KiddoV/wails-pure-js-template) - A template with nothing but just basic JavaScript, HTML, and CSS diff --git a/website/versioned_docs/version-v2.8.0/gettingstarted/_category_.json b/website/versioned_docs/version-v2.8.0/gettingstarted/_category_.json new file mode 100644 index 00000000000..597b920dff9 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/gettingstarted/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Getting Started", + "position": 10 +} diff --git a/website/versioned_docs/version-v2.6.0/gettingstarted/building.mdx b/website/versioned_docs/version-v2.8.0/gettingstarted/building.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/gettingstarted/building.mdx rename to website/versioned_docs/version-v2.8.0/gettingstarted/building.mdx diff --git a/website/versioned_docs/version-v2.6.0/gettingstarted/development.mdx b/website/versioned_docs/version-v2.8.0/gettingstarted/development.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/gettingstarted/development.mdx rename to website/versioned_docs/version-v2.8.0/gettingstarted/development.mdx diff --git a/website/versioned_docs/version-v2.6.0/gettingstarted/firstproject.mdx b/website/versioned_docs/version-v2.8.0/gettingstarted/firstproject.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/gettingstarted/firstproject.mdx rename to website/versioned_docs/version-v2.8.0/gettingstarted/firstproject.mdx diff --git a/website/versioned_docs/version-v2.6.0/gettingstarted/installation.mdx b/website/versioned_docs/version-v2.8.0/gettingstarted/installation.mdx similarity index 96% rename from website/versioned_docs/version-v2.6.0/gettingstarted/installation.mdx rename to website/versioned_docs/version-v2.8.0/gettingstarted/installation.mdx index 19ba0246555..331ca5062df 100644 --- a/website/versioned_docs/version-v2.6.0/gettingstarted/installation.mdx +++ b/website/versioned_docs/version-v2.8.0/gettingstarted/installation.mdx @@ -69,11 +69,7 @@ import TabItem from "@theme/TabItem"; ## Installing Wails -To install the Wails CLI, run the following command: - -```shell -go install github.com/wailsapp/wails/v2/cmd/wails@latest -``` +Run `go install github.com/wailsapp/wails/v2/cmd/wails@latest` to install the Wails CLI. Note: If you get an error similar to this: diff --git a/website/versioned_docs/version-v2.8.0/guides/_category_.json b/website/versioned_docs/version-v2.8.0/guides/_category_.json new file mode 100644 index 00000000000..5935dad936c --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/guides/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Guides", + "position": 50 +} diff --git a/website/versioned_docs/version-v2.6.0/guides/angular.mdx b/website/versioned_docs/version-v2.8.0/guides/angular.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/angular.mdx rename to website/versioned_docs/version-v2.8.0/guides/angular.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/application-development.mdx b/website/versioned_docs/version-v2.8.0/guides/application-development.mdx similarity index 87% rename from website/versioned_docs/version-v2.6.0/guides/application-development.mdx rename to website/versioned_docs/version-v2.8.0/guides/application-development.mdx index 9d04fe9172d..78a6df3bcf1 100644 --- a/website/versioned_docs/version-v2.6.0/guides/application-development.mdx +++ b/website/versioned_docs/version-v2.8.0/guides/application-development.mdx @@ -144,6 +144,65 @@ func main() { } ``` +Also you might want to use Enums in your structs and have models for them on frontend. +In that case you should create array that will contain all possible enum values, instrument enum type and bind it to the app: + +```go {16-18} title="app.go" +type Weekday string + +const ( + Sunday Weekday = "Sunday" + Monday Weekday = "Monday" + Tuesday Weekday = "Tuesday" + Wednesday Weekday = "Wednesday" + Thursday Weekday = "Thursday" + Friday Weekday = "Friday" + Saturday Weekday = "Saturday" +) + +var AllWeekdays = []struct { + Value Weekday + TSName string +}{ + {Sunday, "SUNDAY"}, + {Monday, "MONDAY"}, + {Tuesday, "TUESDAY"}, + {Wednesday, "WEDNESDAY"}, + {Thursday, "THURSDAY"}, + {Friday, "FRIDAY"}, + {Saturday, "SATURDAY"}, +} +``` + +In the main application configuration, the `EnumBind` key is where we can tell Wails what we want to bind enums as well: + +```go {11-13} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + EnumBind: []interface{}{ + AllWeekdays, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +This will add missing enums to your `model.ts` file. + More information on Binding can be found [here](../howdoesitwork.mdx#method-binding). ## Application Menu diff --git a/website/versioned_docs/version-v2.8.0/guides/crossplatform-build.mdx b/website/versioned_docs/version-v2.8.0/guides/crossplatform-build.mdx new file mode 100644 index 00000000000..a9afc616119 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/guides/crossplatform-build.mdx @@ -0,0 +1,65 @@ +# Crossplatform build with Github Actions + +To build a Wails project for all the available platforms, you need to create an application build for each operating system. One effective method to achieve this is by utilizing GitHub Actions. + +An action that facilitates building a Wails app is available at: +https://github.com/dAppServer/wails-build-action + +In case the existing action doesn't fulfill your requirements, you can select only the necessary steps from the source: +https://github.com/dAppServer/wails-build-action/blob/main/action.yml + +Below is a comprehensive example that demonstrates building an app upon the creation of a new Git tag and subsequently uploading it to the Actions artifacts: + +```yaml +name: Wails build + +on: + push: + tags: + # Match any new tag + - '*' + +env: + # Necessary for most environments as build failure can occur due to OOM issues + NODE_OPTIONS: "--max-old-space-size=4096" + +jobs: + build: + strategy: + # Failure in one platform build won't impact the others + fail-fast: false + matrix: + build: + - name: 'App' + platform: 'linux/amd64' + os: 'ubuntu-latest' + - name: 'App' + platform: 'windows/amd64' + os: 'windows-latest' + - name: 'App' + platform: 'darwin/universal' + os: 'macos-latest' + + runs-on: ${{ matrix.build.os }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Build wails + uses: dAppServer/wails-build-action@v2.2 + id: build + with: + build-name: ${{ matrix.build.name }} + build-platform: ${{ matrix.build.platform }} + package: false + go-version: '1.20' +``` + +This example offers opportunities for various enhancements, including: +- Caching dependencies +- Code signing +- Uploading to platforms like S3, Supbase, etc. +- Injecting secrets as environment variables +- Utilizing environment variables as build variables (such as version variable extracted from the current Git tag) diff --git a/website/versioned_docs/version-v2.8.0/guides/custom-protocol-schemes.mdx b/website/versioned_docs/version-v2.8.0/guides/custom-protocol-schemes.mdx new file mode 100644 index 00000000000..c56634f0eb0 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/guides/custom-protocol-schemes.mdx @@ -0,0 +1,189 @@ +# Custom Protocol Scheme association + +Custom Protocols feature allows you to associate specific custom protocol with your app so that when users open links with this protocol, +your app is launched to handle them. This can be particularly useful to connect your desktop app with your web app. +In this guide, we'll walk through the steps to implement custom protocols in Wails app. + + +## Set Up Custom Protocol Schemes Association: +To set up custom protocol, you need to modify your application's wails.json file. +In "info" section add a "protocols" section specifying the protocols your app should be associated with. + +For example: +```json +{ + "info": { + "protocols": [ + { + "scheme": "myapp", + "description": "My App Protocol", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +|:------------|:--------------------------------------------------------------------------------------| +| scheme | Custom Protocol scheme. e.g. myapp | +| description | Windows-only. The description. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS +When you open custom protocol with your app, the system will launch your app and call the `OnUrlOpen` function in your Wails app. Example: +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnUrlOpen: func(url string) { println(url) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + + +### Windows +On Windows Custom Protocol Schemes is supported only with NSIS installer. During installation, the installer will create a +registry entry for your schemes. When you open url with your app, new instance of app is launched and url is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there (note that `%u` is important in Exec). Example: +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=x-scheme-handler/myapp; +``` + +2. Prepare postInstall/postRemove scripts for your package. Example: +```sh +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +``` +3. Configure nfpm to use your scripts and files. Example: +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` +6. Build your .deb package using nfpm: +```sh +nfpm pkg --packager deb --target . +``` +7. Now when your package is installed, your app will be associated with custom protocol scheme. When you open url with your app, +new instance of app is launched and file path is passed as argument to your app. +To handle this you should parse command line arguments in your app. Example: +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/versioned_docs/version-v2.6.0/guides/dynamic-assets.mdx b/website/versioned_docs/version-v2.8.0/guides/dynamic-assets.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/dynamic-assets.mdx rename to website/versioned_docs/version-v2.8.0/guides/dynamic-assets.mdx diff --git a/website/versioned_docs/version-v2.8.0/guides/file-association.mdx b/website/versioned_docs/version-v2.8.0/guides/file-association.mdx new file mode 100644 index 00000000000..71bbff37ead --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/guides/file-association.mdx @@ -0,0 +1,228 @@ +# File Association + +File association feature allows you to associate specific file types with your app so that when users open those files, +your app is launched to handle them. This can be particularly useful for text editors, image viewers, or any application +that works with specific file formats. In this guide, we'll walk through the steps to implement file association in Wails app. + + +## Set Up File Association: +To set up file association, you need to modify your application's wails.json file. +In "info" section add a "fileAssociations" section specifying the file types your app should be associated with. + +For example: +```json +{ + "info": { + "fileAssociations": [ + { + "ext": "wails", + "name": "Wails", + "description": "Wails Application File", + "iconName": "wailsFileIcon", + "role": "Editor" + }, + { + "ext": "jpg", + "name": "JPEG", + "description": "Image File", + "iconName": "jpegFileIcon", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +|:------------|:---------------------------------------------------------------------------------------------------------------------------------------------------| +| ext | The extension (minus the leading period). e.g. png | +| name | The name. e.g. PNG File | +| iconName | The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows | +| description | Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS +When you open file (or files) with your app, the system will launch your app and call the `OnFileOpen` function in your Wails app. Example: +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnFileOpen: func(filePaths []string) { println(filestring) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + + +### Windows +On Windows file association is supported only with NSIS installer. During installation, the installer will create a +registry entry for your file associations. When you open file with your app, new instance of app is launched and file path is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there. Example: +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=application/x-wails;application/x-test +``` + +2. Create mime types file. Example: +```xml + + + + Wails Application File + + + +``` + +3. Create icons for your file types. SVG icons are recommended. +4. Prepare postInstall/postRemove scripts for your package. Example: +```sh +# reload mime types to register file associations +update-mime-database /usr/share/mime +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +# update icons +update-icon-caches /usr/share/icons/* +``` +5. Configure nfpm to use your scripts and files. Example: +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp " +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ./application-wails-mime.xml + dst: /usr/share/mime/packages/application-x-wails.xml +- src: ./application-test-mime.xml + dst: /usr/share/mime/packages/application-x-test.xml +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` +6. Build your .deb package using nfpm: +```sh +nfpm pkg --packager deb --target . +``` +7. Now when your package is installed, your app will be associated with specified file types. When you open file with your app, +new instance of app is launched and file path is passed as argument to your app. +To handle this you should parse command line arguments in your app. Example: +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/versioned_docs/version-v2.6.0/guides/frameless.mdx b/website/versioned_docs/version-v2.8.0/guides/frameless.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/frameless.mdx rename to website/versioned_docs/version-v2.8.0/guides/frameless.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/frontend.mdx b/website/versioned_docs/version-v2.8.0/guides/frontend.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/frontend.mdx rename to website/versioned_docs/version-v2.8.0/guides/frontend.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/ides.mdx b/website/versioned_docs/version-v2.8.0/guides/ides.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/ides.mdx rename to website/versioned_docs/version-v2.8.0/guides/ides.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/linux-distro-support.mdx b/website/versioned_docs/version-v2.8.0/guides/linux-distro-support.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/linux-distro-support.mdx rename to website/versioned_docs/version-v2.8.0/guides/linux-distro-support.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/linux.mdx b/website/versioned_docs/version-v2.8.0/guides/linux.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/linux.mdx rename to website/versioned_docs/version-v2.8.0/guides/linux.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/local-development.mdx b/website/versioned_docs/version-v2.8.0/guides/local-development.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/local-development.mdx rename to website/versioned_docs/version-v2.8.0/guides/local-development.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/mac-appstore.mdx b/website/versioned_docs/version-v2.8.0/guides/mac-appstore.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/mac-appstore.mdx rename to website/versioned_docs/version-v2.8.0/guides/mac-appstore.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/manual-builds.mdx b/website/versioned_docs/version-v2.8.0/guides/manual-builds.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/manual-builds.mdx rename to website/versioned_docs/version-v2.8.0/guides/manual-builds.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/migrating.mdx b/website/versioned_docs/version-v2.8.0/guides/migrating.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/migrating.mdx rename to website/versioned_docs/version-v2.8.0/guides/migrating.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/mouse-buttons.mdx b/website/versioned_docs/version-v2.8.0/guides/mouse-buttons.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/mouse-buttons.mdx rename to website/versioned_docs/version-v2.8.0/guides/mouse-buttons.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/obfuscated.mdx b/website/versioned_docs/version-v2.8.0/guides/obfuscated.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/obfuscated.mdx rename to website/versioned_docs/version-v2.8.0/guides/obfuscated.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/overscroll.mdx b/website/versioned_docs/version-v2.8.0/guides/overscroll.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/overscroll.mdx rename to website/versioned_docs/version-v2.8.0/guides/overscroll.mdx diff --git a/website/versioned_docs/version-v2.8.0/guides/routing.mdx b/website/versioned_docs/version-v2.8.0/guides/routing.mdx new file mode 100644 index 00000000000..ce176943ea5 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/guides/routing.mdx @@ -0,0 +1,47 @@ +# Routing + +Routing is a popular way to switch views in an application. This page offers some guidance around how to do that. + +## Vue + +The recommended approach for routing in Vue is [Hash Mode](https://next.router.vuejs.org/guide/essentials/history-mode.html#hash-mode): + +```js +import { createRouter, createWebHashHistory } from "vue-router"; + +const router = createRouter({ + history: createWebHashHistory(), + routes: [ + //... + ], +}); +``` + +## Angular + +The recommended approach for routing in Angular is [HashLocationStrategy](https://codecraft.tv/courses/angular/routing/routing-strategies#_hashlocationstrategy): + +```ts +RouterModule.forRoot(routes, { useHash: true }); +``` + +## React + +The recommended approach for routing in React is [HashRouter](https://reactrouter.com/en/main/router-components/hash-router): + +```jsx +import { HashRouter } from "react-router-dom"; + +ReactDOM.render( + + {/* The rest of your app goes here */} + + } exact /> + } /> + } /> + {/* more... */} + + , + root +); +``` diff --git a/website/versioned_docs/version-v2.6.0/guides/signing.mdx b/website/versioned_docs/version-v2.8.0/guides/signing.mdx similarity index 94% rename from website/versioned_docs/version-v2.6.0/guides/signing.mdx rename to website/versioned_docs/version-v2.8.0/guides/signing.mdx index b2a060c5f62..e57e99e76de 100644 --- a/website/versioned_docs/version-v2.6.0/guides/signing.mdx +++ b/website/versioned_docs/version-v2.8.0/guides/signing.mdx @@ -232,7 +232,7 @@ jobs: path: build/bin/* ``` -For code signing on macOS, [gon](https://github.com/mitchellh/gon) is a very handy tool for code signing and communicating with Apple servers, also written in Go, and +For code signing on macOS, [gon](https://github.com/Bearer/gon) is a very handy tool for code signing and communicating with Apple servers, also written in Go, and will be used in this guide. After the `Build Wails app` step, add the following to the workflow: @@ -241,7 +241,7 @@ After the `Build Wails app` step, add the following to the workflow: - name: MacOS download gon for code signing and app notarization if: matrix.platform == 'macos-latest' run: | - brew install mitchellh/gon/gon + brew install Bearer/tap/gon ``` Now we need to configure some gon config files in our `build/darwin` directory: @@ -254,19 +254,30 @@ Now we need to configure some gon config files in our `build/darwin` directory: "bundle_id": "app.myapp", "apple_id": { "username": "my-appleid@email.com", - "password": "@env:APPLE_PASSWORD" + "password": "@env:APPLE_PASSWORD", + "provider": "ABCDE12345" }, "sign": { - "application_identity": "Developer ID Application: My Name" + "application_identity": "Developer ID Application: Human User" } } ``` -Where `source` is your Wails binary, `bundle_id` is your bundle ID, `apple_id` contains your Apple ID username and App-Specific password -which you created earlier, and `sign.application_identity` is your identity which you can find by running the following command: +Here is a brief break down of the above fields: + +- `source`: The location of your wails binary to be signed +- `apple_id`: + - `username`: Your Apple ID email address + - `password`: Your app-specific password, referenced using Gon's environment variable syntax + - `provider`: Your team ID for your App Store Connect account +- `sign`: + - `application_identity`: Your Apple developer identity + +Your developer identity and team ID can both by found on macOS by running the following command: ```bash -security find-identity -v -p codesigning +$ security find-identity -v -p codesigning + 1) 00000000000000000000000000000000000000000 "Developer ID Application: Human User (ABCDE12345)" ``` 2. entitlements.plist: @@ -369,7 +380,7 @@ jobs: - name: MacOS download gon for code signing and app notarization if: matrix.platform == 'macos-latest' run: | - brew install mitchellh/gon/gon + brew install Bearer/tap/gon - name: Import Code-Signing Certificates for macOS if: matrix.platform == 'macos-latest' uses: Apple-Actions/import-codesign-certs@v1 diff --git a/website/versioned_docs/version-v2.8.0/guides/single-instance-lock.mdx b/website/versioned_docs/version-v2.8.0/guides/single-instance-lock.mdx new file mode 100644 index 00000000000..644e1e0d80c --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/guides/single-instance-lock.mdx @@ -0,0 +1,80 @@ +# Single Instance Lock + +Single instance lock is a mechanism that allows you to prevent multiple instances of your app from running at the same time. +It is useful for apps that are designed to open files from the command line or from the OS file explorer. + +## Important + +Single Instance Lock does not implement a secure communications protocol between instances. When using single instance lock, +your app should treat any data passed to it from second instance callback as untrusted. +You should verify that args that you receive are valid and don't contain any malicious data. + +## How it works + +Windows: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via a shared window using [SendMessage](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage) +macOS: Single instance lock is implemented using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via [NSDistributedNotificationCenter](https://developer.apple.com/documentation/foundation/nsdistributednotificationcenter) +Linux: Single instance lock is implemented using [dbus](https://www.freedesktop.org/wiki/Software/dbus/). The dbus name is generated from the unique id that you provide. Data is passed to the first instance via [dbus](https://www.freedesktop.org/wiki/Software/dbus/) + +## Usage +When creating your app, you can enable single instance lock by passing a `SingleInstanceLock` struct to the `App` struct. +Use the `UniqueId` field to specify a unique id for your app. +This id is used to generate the mutex name on Windows and macOS and the dbus name on Linux. Use a UUID to ensure that the id is unique. +The `OnSecondInstanceLaunch` field is used to specify a callback that is called when a second instance of your app is launched. +The callback receives a `SecondInstanceData` struct that contains the command line arguments passed to the second instance and the working directory of the second instance. + +Note that OnSecondInstanceLaunch don't trigger windows focus. +You need to call `runtime.WindowUnminimise` and `runtime.Show` to bring your app to the front. +Note that on linux systems window managers may prevent your app from being brought to the front to avoid stealing focus. + +```go title="main.go" +var wailsContext *context.Context + +// NewApp creates a new App application struct +func NewApp() *App { + return &App{} +} + +// startup is called when the app starts. The context is saved +// so we can call the runtime methods +func (a *App) startup(ctx context.Context) { + wailsContext = &ctx +} + +func (a *App) onSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) { + secondInstanceArgs = secondInstanceData.Args + + println("user opened second instance", strings.Join(secondInstanceData.Args, ",")) + println("user opened second from", secondInstanceData.WorkingDirectory) + runtime.WindowUnminimise(*wailsContext) + runtime.Show(*wailsContext) + go runtime.EventsEmit(*wailsContext, "launchArgs", secondInstanceArgs) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + OnStartup: app.startup, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` diff --git a/website/versioned_docs/version-v2.6.0/guides/sveltekit.mdx b/website/versioned_docs/version-v2.8.0/guides/sveltekit.mdx similarity index 98% rename from website/versioned_docs/version-v2.6.0/guides/sveltekit.mdx rename to website/versioned_docs/version-v2.8.0/guides/sveltekit.mdx index 3f82eb813eb..e0357ca3c51 100644 --- a/website/versioned_docs/version-v2.6.0/guides/sveltekit.mdx +++ b/website/versioned_docs/version-v2.8.0/guides/sveltekit.mdx @@ -24,6 +24,9 @@ This guide will go into: ##### Modify main.go. - The first comment `//go:embed all:frontend/dist` needs to be changed to `//go:embed all:frontend/build` +##### Modify .gitignore +- The line `frontend/dist` needs to be replaced with `frontend/build` + ##### Install/remove dependencies using your favorite package manager. - Navigate into your "frontend" folder. - `npm i` diff --git a/website/versioned_docs/version-v2.6.0/guides/templates.mdx b/website/versioned_docs/version-v2.8.0/guides/templates.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/templates.mdx rename to website/versioned_docs/version-v2.8.0/guides/templates.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/troubleshooting.mdx b/website/versioned_docs/version-v2.8.0/guides/troubleshooting.mdx similarity index 55% rename from website/versioned_docs/version-v2.6.0/guides/troubleshooting.mdx rename to website/versioned_docs/version-v2.8.0/guides/troubleshooting.mdx index bd965a79901..3bff4e44ffa 100644 --- a/website/versioned_docs/version-v2.6.0/guides/troubleshooting.mdx +++ b/website/versioned_docs/version-v2.8.0/guides/troubleshooting.mdx @@ -173,6 +173,28 @@ If `/Applications/Xcode.app/Contents/Developer` is displayed, run `sudo xcode-se Sources: https://github.com/wailsapp/wails/issues/1806 and https://github.com/wailsapp/wails/issues/1140#issuecomment-1290446496 +## My application won't compile on Mac + +If you are getting errors like this: + +```shell +l1@m2 GoEasyDesigner % go build -tags dev -gcflags "all=-N -l" +/Users/l1/sdk/go1.20.5/pkg/tool/darwin_arm64/link: running clang failed: exit status 1 +Undefined symbols for architecture arm64: + "_OBJC_CLASS_$_UTType", referenced from: + objc-class-ref in 000016.o +ld: symbol(s) not found for architecture arm64 +clang: error: linker command failed with exit code 1 (use -v to see invocation) +``` +Ensure you have the latest SDK installed. If so and you're still experiencing this issue, try the following: + +```shell +export CGO_LDFLAGS="-framework UniformTypeIdentifiers" && go build -tags dev -gcflags "all=-N -l" +``` + +Sources: https://github.com/wailsapp/wails/pull/2925#issuecomment-1726828562 + + -- ## Cannot start service: Host version "x.x.x does not match binary version "x.x.x" @@ -201,4 +223,163 @@ you can make the webview background transparent using the following config: WebviewIsTransparent: true, }, }) -``` \ No newline at end of file +``` + +## I get a "Microsoft Edge can't read or write to its data directory" error when running my program as admin on Windows + +You set your program to require admin permissions and it worked great! Unfortunately, some users are seeing a "Microsoft Edge can't read or write to its data directory" error when running it. + +When a Windows machine has two local accounts: + +- Alice, an admin +- Bob, a regular user + +Bob sees a UAC prompt when running your program. Bob enters Alice's admin credentials into this prompt. The app launches with admin permissions under Alice's account. + +Wails instructs WebView2 to store user data at the specified `WebviewUserDataPath`. It defaults to `%APPDATA%\[BinaryName.exe]`. + +Because the application is running under Alice's account, `%APPDATA%\[BinaryName.exe]` resolves to `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`. + +WebView2 [creates some child processes under Bob's logged-in account instead of Alice's admin account](https://github.com/MicrosoftEdge/WebView2Feedback/issues/932#issue-807464179). Since Bob cannot access `C:\Users\Alice\AppData\Roaming\[BinaryName.exe]`, the "Microsoft Edge can't read or write to its data directory" error is shown. + +Possible solution #1: + +Refactor your application to work without constant admin permissions. If you just need to perform a small set of admin tasks (such as running an updater), you can run your application with the minimum permissions and then use the `runas` command to run these tasks with admin permissions as needed: + +```go +//go:build windows + +package sample + +import ( + "golang.org/x/sys/windows" + "syscall" +) + +// Calling RunAs("C:\path\to\my\updater.exe") shows Bob a UAC prompt. Bob enters Alice's admin credentials. The updater launches with admin permissions under Alice's account. +func RunAs(path string) error { + verbPtr, _ := syscall.UTF16PtrFromString("runas") + exePtr, _ := syscall.UTF16PtrFromString(path) + cwdPtr, _ := syscall.UTF16PtrFromString("") + argPtr, _ := syscall.UTF16PtrFromString("") + + var showCmd int32 = 1 //SW_NORMAL + + err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd) + if err != nil { + return err + } + return nil +} +``` + +Possible solution #2: + +Run your application with extended permissions. If you absolutely must run with constant admin permissions, WebView2 will function correctly if you use a data directory accessible by both users and you also launch your app with the `SeBackupPrivilege`, `SeDebugPrivilege`, and `SeRestorePrivilege` permissions. Here's an example: + +```go +package main + +import ( + "embed" + "os" + "runtime" + + "github.com/fourcorelabs/wintoken" + "github.com/hectane/go-acl" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "github.com/wailsapp/wails/v2/pkg/options/windows" +) + +//go:embed all:frontend/dist +var assets embed.FS + +const ( + fixedTokenKey = "SAMPLE_RANDOM_KEY" + fixedTokenVal = "with-fixed-token" + webviewDir = "C:\\ProgramData\\Sample" +) + +func runWithFixedToken() { + println("Re-launching self") + token, err := wintoken.OpenProcessToken(0, wintoken.TokenPrimary) //pass 0 for own process + if err != nil { + panic(err) + } + defer token.Close() + + token.EnableTokenPrivileges([]string{ + "SeBackupPrivilege", + "SeDebugPrivilege", + "SeRestorePrivilege", + }) + + cmd := exec.Command(os.Args[0]) + cmd.Args = os.Args + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, fmt.Sprintf("%v=%v", fixedTokenKey, fixedTokenVal)) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.SysProcAttr = &syscall.SysProcAttr{Token: syscall.Token(token.Token())} + if err := cmd.Run(); err != nil { + println("Error after launching self:", err) + os.Exit(1) + } + println("Clean self launch :)") + os.Exit(0) +} + +func main() { + if runtime.GOOS == "windows" && os.Getenv(fixedTokenKey) != fixedTokenVal { + runWithFixedToken() + } + + println("Setting data dir to", webviewDir) + if err := os.MkdirAll(webviewDir, os.ModePerm); err != nil { + println("Failed creating dir:", err) + } + if err := acl.Chmod(webviewDir, 0777); err != nil { + println("Failed setting ACL on dir:", err) + } + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "sample-data-dir", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + }, + Windows: &windows.Options{ + WebviewUserDataPath: webviewDir, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +If you use a data directory accessible by both users but not the extended privileges, you will receive a WebView2 `80010108 The object invoked has disconnected from its clients` error. + +Possible future solution #3: [run WebView2 using an in-memory mode if implemented](https://github.com/MicrosoftEdge/WebView2Feedback/issues/3637#issuecomment-1728300982). + +## WebView2 installation succeeded, but the wails doctor command shows that it is not installed + +If you have installed WebView2, but the `wails doctor` command shows that it is not installed, it is likely that the +WebView2 runtime installed was for a different architecture. You can download the correct runtime from [here](https://developer.microsoft.com/en-us/microsoft-edge/webview2/). + +Source: https://github.com/wailsapp/wails/issues/2917 + +## WebVie2wProcess failed with kind + +If your Windows app generates this kind of error, you can check out what the error means [here](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2processfailedkind?view=webview2-winrt-1.0.2045.28). + diff --git a/website/versioned_docs/version-v2.6.0/guides/vscode.mdx b/website/versioned_docs/version-v2.8.0/guides/vscode.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/vscode.mdx rename to website/versioned_docs/version-v2.8.0/guides/vscode.mdx diff --git a/website/versioned_docs/version-v2.6.0/guides/windows-installer.mdx b/website/versioned_docs/version-v2.8.0/guides/windows-installer.mdx similarity index 79% rename from website/versioned_docs/version-v2.6.0/guides/windows-installer.mdx rename to website/versioned_docs/version-v2.8.0/guides/windows-installer.mdx index 53373488660..c65dc6d3422 100644 --- a/website/versioned_docs/version-v2.6.0/guides/windows-installer.mdx +++ b/website/versioned_docs/version-v2.8.0/guides/windows-installer.mdx @@ -18,13 +18,26 @@ Wails supports generating Windows installers using the [NSIS installer](https:// The installer is available on the [NSIS Download](https://nsis.sourceforge.io/Download) page. +You can install with [Scoop](https://scoop.sh/) (which will automatically add it to your PATH): + +``` +scoop add bucket extras +scoop install nsis +``` + +Or, you can use Winget (on Windows 10+): + +``` +winget install NSIS.NSIS --silent +``` + If you use the chocolatey package manager, run the following script: ``` choco install nsis ``` -If you install NSIS manually, you need to add the _Bin_ folder, which contains `makensis.exe`, in your NSIS installation to your path. +**NOTE:** If you install NSIS manually, you need to add the _Bin_ folder, which contains `makensis.exe`, in your NSIS installation to your path. [Here](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/) is a good tutorial on how to add to path on Windows. ### Linux diff --git a/website/versioned_docs/version-v2.6.0/guides/windows.mdx b/website/versioned_docs/version-v2.8.0/guides/windows.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/guides/windows.mdx rename to website/versioned_docs/version-v2.8.0/guides/windows.mdx diff --git a/website/versioned_docs/version-v2.6.0/howdoesitwork.mdx b/website/versioned_docs/version-v2.8.0/howdoesitwork.mdx similarity index 93% rename from website/versioned_docs/version-v2.6.0/howdoesitwork.mdx rename to website/versioned_docs/version-v2.8.0/howdoesitwork.mdx index e9f2c6e3dc4..6e23d5eb94d 100644 --- a/website/versioned_docs/version-v2.6.0/howdoesitwork.mdx +++ b/website/versioned_docs/version-v2.8.0/howdoesitwork.mdx @@ -206,6 +206,57 @@ You may bind as many structs as you like. Just make sure you create an instance ``` +You may bind enums types as well. +In that case you should create array that will contain all possible enum values, instrument enum type and bind it to the app via `EnumBind`: + +```go {16-18} title="app.go" +type Weekday string + +const ( + Sunday Weekday = "Sunday" + Monday Weekday = "Monday" + Tuesday Weekday = "Tuesday" + Wednesday Weekday = "Wednesday" + Thursday Weekday = "Thursday" + Friday Weekday = "Friday" + Saturday Weekday = "Saturday" +) + +var AllWeekdays = []struct { + Value Weekday + TSName string +}{ + {Sunday, "SUNDAY"}, + {Monday, "MONDAY"}, + {Tuesday, "TUESDAY"}, + {Wednesday, "WEDNESDAY"}, + {Thursday, "THURSDAY"}, + {Friday, "FRIDAY"}, + {Saturday, "SATURDAY"}, +} +``` + +```go {10-12} + //... + err := wails.Run(&options.App{ + Title: "Basic Demo", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Bind: []interface{}{ + app, + &mystruct1{}, + &mystruct2{}, + }, + EnumBind: []interface{}{ + AllWeekdays, + }, + }) + +``` + When you run `wails dev` (or `wails generate module`), a frontend module will be generated containing the following: - JavaScript bindings for all bound methods diff --git a/website/versioned_docs/version-v2.6.0/introduction.mdx b/website/versioned_docs/version-v2.8.0/introduction.mdx similarity index 97% rename from website/versioned_docs/version-v2.6.0/introduction.mdx rename to website/versioned_docs/version-v2.8.0/introduction.mdx index 1bfa099e80f..98f42806fa9 100644 --- a/website/versioned_docs/version-v2.6.0/introduction.mdx +++ b/website/versioned_docs/version-v2.8.0/introduction.mdx @@ -48,7 +48,7 @@ and TypeScript versions for each template. Wails uses a purpose built library for handling native elements such as Window, Menus, Dialogs, etc, so you can build good-looking, feature rich desktop applications. -**It does not embed a browser**, so it is resource efficient. Instead, it uses the native rendering engine for the +**It does not embed a browser**, so it delivers a small runtime. Instead, it reuses the native rendering engine for the platform. On Windows, this is the new Microsoft Webview2 library, built on Chromium. ### Go & JavaScript Interoperability diff --git a/website/versioned_docs/version-v2.8.0/reference/_category_.json b/website/versioned_docs/version-v2.8.0/reference/_category_.json new file mode 100644 index 00000000000..ebb337b8360 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/reference/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Reference", + "position": 40 +} diff --git a/website/versioned_docs/version-v2.6.0/reference/cli.mdx b/website/versioned_docs/version-v2.8.0/reference/cli.mdx similarity index 78% rename from website/versioned_docs/version-v2.6.0/reference/cli.mdx rename to website/versioned_docs/version-v2.8.0/reference/cli.mdx index 9dcc25bc938..dc8b3293f81 100644 --- a/website/versioned_docs/version-v2.6.0/reference/cli.mdx +++ b/website/versioned_docs/version-v2.8.0/reference/cli.mdx @@ -52,35 +52,35 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for `wails build` is used for compiling your project to a production-ready binary. -| Flag | Description | Default | -|:---------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------| -| -clean | Cleans the `build/bin` directory | | -| -compiler "compiler" | Use a different go compiler to build, eg go1.15beta1 | go | -| -debug | Retains debug information in the application and shows the debug console. Allows the use of the devtools in the application window | | -| -devtools | Allows the use of the devtools in the application window in production (when -debug is not used) | | -| -dryrun | Prints the build command without executing it | | -| -f | Force build application | | -| -garbleargs | Arguments to pass to garble | `-literals -tiny -seed=random` | -| -ldflags "flags" | Additional ldflags to pass to the compiler | | -| -m | Skip mod tidy before compile | | -| -nopackage | Do not package application | | -| -nocolour | Disable colour in output | | -| -nosyncgomod | Do not sync go.mod with the Wails version | | -| -nsis | Generate NSIS installer for Windows | | -| -o filename | Output filename | | -| -obfuscated | Obfuscate the application using [garble](https://github.com/burrowers/garble) | | -| -platform | Build for the given (comma delimited) [platforms](../reference/cli.mdx#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | platform = `GOOS` environment variable if given else `runtime.GOOS`.
arch = `GOARCH` envrionment variable if given else `runtime.GOARCH`. | -| -race | Build with Go's race detector | | -| -s | Skip building the frontend | | -| -skipbindings | Skip bindings generation | | -| -tags "extra tags" | Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated | | -| -trimpath | Remove all file system paths from the resulting executable. | | -| -u | Updates your project's `go.mod` to use the same version of Wails as the CLI | | -| -upx | Compress final binary using "upx" | | -| -upxflags | Flags to pass to upx | | -| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 | -| -webview2 | WebView2 installer strategy: download,embed,browser,error | download | -| -windowsconsole | Keep the console window for Windows builds | | +| Flag | Description | Default | +|:---------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------| +| -clean | Cleans the `build/bin` directory | | +| -compiler "compiler" | Use a different go compiler to build, eg go1.15beta1 | go | +| -debug | Retains debug information in the application and shows the debug console. Allows the use of the devtools in the application window | | +| -devtools | Allows the use of the devtools in the application window in production (when -debug is not used). Ctrl/Cmd+Shift+F12 may be used to open the devtools window. *NOTE*: This option will make your application FAIL Mac appstore guidelines. Use for debugging only. | | +| -dryrun | Prints the build command without executing it | | +| -f | Force build application | | +| -garbleargs | Arguments to pass to garble | `-literals -tiny -seed=random` | +| -ldflags "flags" | Additional ldflags to pass to the compiler | | +| -m | Skip mod tidy before compile | | +| -nopackage | Do not package application | | +| -nocolour | Disable colour in output | | +| -nosyncgomod | Do not sync go.mod with the Wails version | | +| -nsis | Generate NSIS installer for Windows | | +| -o filename | Output filename | | +| -obfuscated | Obfuscate the application using [garble](https://github.com/burrowers/garble) | | +| -platform | Build for the given (comma delimited) [platforms](../reference/cli.mdx#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | platform = `GOOS` environment variable if given else `runtime.GOOS`.
arch = `GOARCH` envrionment variable if given else `runtime.GOARCH`. | +| -race | Build with Go's race detector | | +| -s | Skip building the frontend | | +| -skipbindings | Skip bindings generation | | +| -tags "extra tags" | Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated | | +| -trimpath | Remove all file system paths from the resulting executable. | | +| -u | Updates your project's `go.mod` to use the same version of Wails as the CLI | | +| -upx | Compress final binary using "upx" | | +| -upxflags | Flags to pass to upx | | +| -v int | Verbosity level (0 - silent, 1 - default, 2 - verbose) | 1 | +| -webview2 | WebView2 installer strategy: download,embed,browser,error | download | +| -windowsconsole | Keep the console window for Windows builds | | For a detailed description of the `webview2` flag, please refer to the [Windows](../guides/windows.mdx) Guide. @@ -170,8 +170,8 @@ Your system is ready for Wails development! - A webserver is started on `http://localhost:34115` which serves your application (not just frontend) over http. This allows you to use your favourite browser development extensions - All application assets are loaded from disk. If they are changed, the application will automatically reload (not rebuild). All connected browsers will also reload - A JS module is generated that provides the following: - - JavaScript wrappers of your Go methods with autogenerated JSDoc, providing code hinting - - TypeScript versions of your Go structs, that can be constructed and passed to your go methods +- JavaScript wrappers of your Go methods with autogenerated JSDoc, providing code hinting +- TypeScript versions of your Go structs, that can be constructed and passed to your go methods - A second JS module is generated that provides a wrapper + TS declaration for the runtime - On macOS, it will bundle the application into a `.app` file and run it. It will use a `build/darwin/Info.dev.plist` for development. @@ -231,6 +231,11 @@ For more details on creating templates, consult the [Templates guide](../guides/ The `wails generate module` command allows you to manually generate the `wailsjs` directory for your application. +| Flag | Description | Default | +|:---------------------|:------------------------------------------------------------|:--------| +| -compiler "compiler" | Use a different go compiler to build, eg go1.15beta1 | go | +| -tags "extra tags" | Build tags to pass to compiler (quoted and space separated) | | + ## update `wails update` will update the version of the Wails CLI. diff --git a/website/versioned_docs/version-v2.6.0/reference/menus.mdx b/website/versioned_docs/version-v2.8.0/reference/menus.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/menus.mdx rename to website/versioned_docs/version-v2.8.0/reference/menus.mdx diff --git a/website/versioned_docs/version-v2.6.0/reference/options.mdx b/website/versioned_docs/version-v2.8.0/reference/options.mdx similarity index 88% rename from website/versioned_docs/version-v2.6.0/reference/options.mdx rename to website/versioned_docs/version-v2.8.0/reference/options.mdx index abeb8a8bba3..26fb1afac27 100644 --- a/website/versioned_docs/version-v2.6.0/reference/options.mdx +++ b/website/versioned_docs/version-v2.8.0/reference/options.mdx @@ -39,7 +39,7 @@ func main() { AssetServer: &assetserver.Options{ Assets: assets, Handler: assetsHandler, - Middleware: assetsMiddleware, + Middleware: assetsMidldeware, }, Menu: app.applicationMenu(), Logger: nil, @@ -56,11 +56,19 @@ func main() { Bind: []interface{}{ app, }, + EnumBind: []interface{}{ + AllWeekdays, + }, ErrorFormatter: func(err error) any { return err.Error() }, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "c9c8fd93-6758-4144-87d1-34bdb0a8bd60", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, Windows: &windows.Options{ WebviewIsTransparent: false, WindowIsTranslucent: false, BackdropType: windows.Mica, + DisablePinchZoom: false, DisableWindowIcon: false, DisableFramelessWindowDecorations: false, WebviewUserDataPath: "", @@ -74,15 +82,18 @@ func main() { LightModeTitleText: windows.RGB(20, 20, 20), LightModeBorder: windows.RGB(200, 200, 200), }, + // ZoomFactor is the zoom factor for the WebView2. This is the option matching the Edge user activated zoom in or out. + ZoomFactor: float64, + // IsZoomControlEnabled enables the zoom factor to be changed by the user. + IsZoomControlEnabled: bool, // User messages that can be customised - Messages *windows.Messages + Messages: *windows.Messages // OnSuspend is called when Windows enters low power mode - OnSuspend func() + OnSuspend: func() // OnResume is called when Windows resumes from low power mode - OnResume func(), - WebviewGpuDisabled: false, - ZoomFactor: 1.0, - IsZoomControlEnabled: false, + OnResume: func(), + // Disable GPU hardware acceleration for the webview + WebviewGpuDisabled: false, }, Mac: &mac.Options{ TitleBar: &mac.TitleBar{ @@ -92,6 +103,8 @@ func main() { FullSizeContent: false, UseToolbar: false, HideToolbarSeparator: true, + OnFileOpen: app.onFileOpen, + OnUrlOpen: app.onUrlOpen, }, Appearance: mac.NSAppearanceNameDarkAqua, WebviewIsTransparent: true, @@ -424,7 +437,7 @@ Type: `string` EnableDefaultContextMenu enables the browser's default context-menu in production. -By default, the browser's default context-menu is only available in development and in a `-debug` or `-devtools` [build](../reference/cli.mdx#build) along with the devtools inspector, Using this option you can enable the default context-menu in `production` while the devtools inspector won't be available unless the `-devtools` build flag is used. +By default, the browser's default context-menu is only available in development and in a `-debug` [build](../reference/cli.mdx#build) along with the devtools inspector, Using this option you can enable the default context-menu in `production` while the devtools inspector won't be available unless the `-devtools` build flag is used. When this option is enabled, by default the context-menu will only be shown for text contexts (where Cut/Copy/Paste is needed), to override this behavior, you can use the CSS property `--default-contextmenu` on any HTML element (including the `body`) with the following values : @@ -457,6 +470,21 @@ services of Apple and Microsoft. Name: EnableFraudulentWebsiteDetection
Type: `bool` +### ZoomFactor + +Name: ZoomFactor
+Type: `float64` + +This defines the zoom factor for the WebView2. This is the option matching the Edge user activated zoom in or out. + +### IsZoomControlEnabled + +Name: IsZoomControlEnabled
+Type: `bool` + +This enables the zoom factor to be changed by the user. Please note that the zoom factor can be set in the options while +disallowing the user to change it at runtime (f.e. for a kiosk application or similar). + ### Bind A slice of struct instances defining methods that need to be bound to the frontend. @@ -464,6 +492,13 @@ A slice of struct instances defining methods that need to be bound to the fronte Name: Bind
Type: `[]interface{}` +### EnumBind + +A slice of Enum arrays that need to be bound to the frontend. + +Name: EnumBind
+Type: `[]interface{}` + ### ErrorFormatter A function that determines how errors are formatted when returned by a JS-to-Go @@ -472,6 +507,28 @@ method call. The returned value will be marshalled as JSON. Name: ErrorFormatter
Type: `func (error) any` +### SingleInstanceLock + +Enables single instance locking. This means that only one instance of your application can be running at a time. + +Name: SingleInstanceLock
+Type: `*options.SingleInstanceLock` + +#### UniqueId + +This id is used to generate the mutex name on Windows and macOS and the dbus name on Linux. Use a UUID to ensure that the id is unique. + +Name: UniqueId
+Type: `string` + +#### OnSecondInstanceLaunch + +Callback that is called when a second instance of your app is launched. + +Name: OnSecondInstanceLaunch
+Type: `func(secondInstanceData SecondInstanceData)` + + ### Windows This defines [Windows specific options](#windows). @@ -524,6 +581,13 @@ The value can be one of the following: | Mica | Use [Mica](https://learn.microsoft.com/en-us/windows/apps/design/style/mica) effect | | Tabbed | Use Tabbed. This is a backdrop that is similar to Mica. | +#### DisablePinchZoom + +Setting this to `true` will disable pinch zoom gestures. + +Name: DisablePinchZoom
+Type: `bool` + #### DisableWindowIcon Setting this to `true` will remove the icon in the top left corner of the title bar. @@ -672,21 +736,13 @@ Setting this to `true` will disable GPU hardware acceleration for the webview. Name: WebviewGpuIsDisabled
Type: `bool` -#### ZoomFactor +#### EnableSwipeGestures -Name: ZoomFactor
-Type: `float64` - -This defines the zoom factor for the WebView2. This is the option matching the Edge user activated zoom in or out. - -#### IsZoomControlEnabled +Setting this to `true` will enable swipe gestures for the webview. -Name: IsZoomControlEnabled
+Name: EnableSwipeGestures
Type: `bool` -This enables the zoom factor to be changed by the user. Please note that the zoom factor can be set in the options while -disallowing the user to change it at runtime (f.e. for a kiosk application or similar). - ### Mac This defines [Mac specific options](#mac). @@ -790,6 +846,57 @@ with [WebviewIsTransparent](#WebviewIsTransparent) to make frosty-looking applic Name: WindowIsTranslucent
Type: `bool` +#### OnFileOpen + +Callback that is called when a file is opened with the application. + +Name: OnFileOpen
+Type: `func(filePath string)` + +#### OnUrlOpen + +Callback that is called when a URL is opened with the application. + +Name: OnUrlOpen
+Type: `func(filePath string)` + +#### Preferences + +The Preferences struct provides the ability to configure the Webview preferences. + +Name: Preferences
+Type: [`*mac.Preferences`](#preferences-struct) + +##### Preferences struct + +You can specify the webview preferences. + +```go +type Preferences struct { + TabFocusesLinks u.Bool + TextInteractionEnabled u.Bool + FullscreenEnabled u.Bool +} +``` + +| Name | Description | +| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| TabFocusesLinks | A Boolean value that indicates whether pressing the tab key changes the focus to links and form controls. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/2818595-tabfocuseslinks?language=objc) | +| TextInteractionEnabled | A Boolean value that indicates whether to allow people to select or otherwise interact with text. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3727362-textinteractionenabled?language=objc) | +| FullscreenEnabled | A Boolean value that indicates whether a web view can display content full screen. [Apple Docs](https://developer.apple.com/documentation/webkit/wkpreferences/3917769-elementfullscreenenabled?language=objc) | + +Example: + +```go +Mac: &mac.Options{ + Preferences: &mac.Preferences{ + TabFocusesLinks: mac.Enabled, + TextInteractionEnabled: mac.Disabled, + FullscreenEnabled: mac.Enabled, + } +} +``` + #### About This configuration lets you set the title, message and icon for the "About" menu item in the app menu created by the "AppMenu" role. diff --git a/website/versioned_docs/version-v2.8.0/reference/project-config.mdx b/website/versioned_docs/version-v2.8.0/reference/project-config.mdx new file mode 100644 index 00000000000..3a6f09495a0 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/reference/project-config.mdx @@ -0,0 +1,130 @@ +--- +sidebar_position: 5 +--- + +# Project Config + +The project config resides in the `wails.json` file in the project directory. The structure of the config is: + +```json5 +{ + // Project config version + "version": "", + // The project name + "name": "", + // Relative path to the directory containing the compiled assets, this is normally inferred and could be left empty + "assetdir": "", + // Additional directories to trigger reloads (comma separated), this is only used for some advanced asset configurations + "reloaddirs": "", + // The directory where the build files reside. Defaults to 'build' + "build:dir": "", + // Relative path to the frontend directory. Defaults to 'frontend' + "frontend:dir": "", + // The command to install node dependencies, run in the frontend directory - often `npm install` + "frontend:install": "", + // The command to build the assets, run in the frontend directory - often `npm run build` + "frontend:build": "", + // This command has been replaced by frontend:dev:build. If frontend:dev:build is not specified will falls back to this command. \nIf this command is also not specified will falls back to frontend:build + "frontend:dev": "", + // This command is the dev equivalent of frontend:build. If not specified falls back to frontend:dev + "frontend:dev:build": "", + // This command is the dev equivalent of frontend:install. If not specified falls back to frontend:install + "frontend:dev:install": "", + // This command is run in a separate process on `wails dev`. Useful for 3rd party watchers or starting 3d party dev servers + "frontend:dev:watcher": "", + // URL to a 3rd party dev server to be used to serve assets, EG Vite. \nIf this is set to 'auto' then the devServerUrl will be inferred from the Vite output + "frontend:dev:serverUrl": "", + // Relative path to the directory that the auto-generated JS modules will be created + "wailsjsdir": "", + // The name of the binary + "outputfilename": "", + // The default time the dev server waits to reload when it detects a change in assets + "debounceMS": 100, + // Address to bind the wails dev sever to. Default: localhost:34115 + "devServer": "", + // Arguments passed to the application in shell style when in dev mode + "appargs": "", + // Defines if build hooks should be run though they are defined for an OS other than the host OS. + "runNonNativeBuildHooks": false, + "preBuildHooks": { + // The command that will be executed before a build of the specified GOOS/GOARCH: ${platform} is replaced with the "GOOS/GOARCH". The "GOOS/GOARCH" hook is executed before the "GOOS/*" and "*/*" hook. + "GOOS/GOARCH": "", + // The command that will be executed before a build of the specified GOOS: ${platform} is replaced with the "GOOS/GOARCH". The "GOOS/*" hook is executed before the "*/*" hook. + "GOOS/*": "", + // The command that will be executed before every build: ${platform} is replaced with the "GOOS/GOARCH". + "*/*": "" + }, + "postBuildHooks": { + // The command that will be executed after a build of the specified GOOS/GOARCH: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. The "GOOS/GOARCH" hook is executed before the "GOOS/*" and "*/*" hook. + "GOOS/GOARCH": "", + // The command that will be executed after a build of the specified GOOS: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. The "GOOS/*" hook is executed before the "*/*" hook. + "GOOS/*": "", + // The command that will be executed after every build: ${platform} is replaced with the "GOOS/GOARCH" and ${bin} with the path to the compiled binary. + "*/*": "" + }, + // Data used to populate manifests and version info. + "info": { + // The company name. Default: [The project name] + "companyName": "", + // The product name. Default: [The project name] + "productName": "", + // The version of the product. Default: '1.0.0' + "productVersion": "", + // The copyright of the product. Default: 'Copyright.........' + "copyright": "", + // A short comment of the app. Default: 'Built using Wails (https://wails.app)' + "comments": "", + // File associations for the app + "fileAssociations": [ + { + // The extension (minus the leading period). e.g. png + "ext": "wails", + // The name. e.g. PNG File + "name": "Wails", + // Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. + "description": "Wails file", + // The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows) + "iconName": "fileIcon", + // macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. + "role": "Editor" + }, + ], + // Custom URI protocols that should be opened by the application + "protocols": [ + { + // protocol scheme. e.g. myapp + "scheme": "myapp", + // Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. + "description": "Myapp protocol", + // macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. + "role": "Editor" + } + ] + }, + // 'multiple': One installer per architecture. 'single': Single universal installer for all architectures being built. Default: 'multiple' + "nsisType": "", + // Whether the app should be obfuscated. Default: false + "obfuscated": "", + // The arguments to pass to the garble command when using the obfuscated flag + "garbleargs": "", + // Bindings configurations + "bindings": { + // model.ts file generation config + "ts_generation": { + // All generated JavaScript entities will be prefixed with this value + "prefix": "", + // All generated JavaScript entities will be suffixed with this value + "suffix": "", + // Type of output to generate (classes|interfaces) + "outputType": "classes", + } + } +} +``` + +This file is read by the Wails CLI when running `wails build` or `wails dev`. + +The `assetdir`, `reloaddirs`, `wailsjsdir`, `debounceMS`, `devserver` and `frontenddevserverurl` flags in `wails build/dev` will update the project config +and thus become defaults for subsequent runs. + +The JSON Schema for this file is located [here](https://wails.io/schemas/config.v2.json). diff --git a/website/versioned_docs/version-v2.8.0/reference/runtime/_category_.json b/website/versioned_docs/version-v2.8.0/reference/runtime/_category_.json new file mode 100644 index 00000000000..ac6d5548816 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/reference/runtime/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Runtime", + "position": 1 +} diff --git a/website/versioned_docs/version-v2.6.0/reference/runtime/browser.mdx b/website/versioned_docs/version-v2.8.0/reference/runtime/browser.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/runtime/browser.mdx rename to website/versioned_docs/version-v2.8.0/reference/runtime/browser.mdx diff --git a/website/versioned_docs/version-v2.6.0/reference/runtime/clipboard.mdx b/website/versioned_docs/version-v2.8.0/reference/runtime/clipboard.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/runtime/clipboard.mdx rename to website/versioned_docs/version-v2.8.0/reference/runtime/clipboard.mdx diff --git a/website/versioned_docs/version-v2.6.0/reference/runtime/dialog.mdx b/website/versioned_docs/version-v2.8.0/reference/runtime/dialog.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/runtime/dialog.mdx rename to website/versioned_docs/version-v2.8.0/reference/runtime/dialog.mdx diff --git a/website/versioned_docs/version-v2.6.0/reference/runtime/events.mdx b/website/versioned_docs/version-v2.8.0/reference/runtime/events.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/runtime/events.mdx rename to website/versioned_docs/version-v2.8.0/reference/runtime/events.mdx diff --git a/website/versioned_docs/version-v2.6.0/reference/runtime/intro.mdx b/website/versioned_docs/version-v2.8.0/reference/runtime/intro.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/runtime/intro.mdx rename to website/versioned_docs/version-v2.8.0/reference/runtime/intro.mdx diff --git a/website/versioned_docs/version-v2.6.0/reference/runtime/log.mdx b/website/versioned_docs/version-v2.8.0/reference/runtime/log.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/runtime/log.mdx rename to website/versioned_docs/version-v2.8.0/reference/runtime/log.mdx diff --git a/website/versioned_docs/version-v2.6.0/reference/runtime/menu.mdx b/website/versioned_docs/version-v2.8.0/reference/runtime/menu.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/runtime/menu.mdx rename to website/versioned_docs/version-v2.8.0/reference/runtime/menu.mdx diff --git a/website/versioned_docs/version-v2.6.0/reference/runtime/screen.mdx b/website/versioned_docs/version-v2.8.0/reference/runtime/screen.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/runtime/screen.mdx rename to website/versioned_docs/version-v2.8.0/reference/runtime/screen.mdx diff --git a/website/versioned_docs/version-v2.6.0/reference/runtime/window.mdx b/website/versioned_docs/version-v2.8.0/reference/runtime/window.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/reference/runtime/window.mdx rename to website/versioned_docs/version-v2.8.0/reference/runtime/window.mdx diff --git a/website/versioned_docs/version-v2.8.0/tutorials/_category_.json b/website/versioned_docs/version-v2.8.0/tutorials/_category_.json new file mode 100644 index 00000000000..dfac1d175e6 --- /dev/null +++ b/website/versioned_docs/version-v2.8.0/tutorials/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Tutorials", + "position": 70 +} diff --git a/website/versioned_docs/version-v2.6.0/tutorials/dogsapi.mdx b/website/versioned_docs/version-v2.8.0/tutorials/dogsapi.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/tutorials/dogsapi.mdx rename to website/versioned_docs/version-v2.8.0/tutorials/dogsapi.mdx diff --git a/website/versioned_docs/version-v2.6.0/tutorials/helloworld.mdx b/website/versioned_docs/version-v2.8.0/tutorials/helloworld.mdx similarity index 100% rename from website/versioned_docs/version-v2.6.0/tutorials/helloworld.mdx rename to website/versioned_docs/version-v2.8.0/tutorials/helloworld.mdx diff --git a/website/versioned_sidebars/version-v2.6.0-sidebars.json b/website/versioned_sidebars/version-v2.8.0-sidebars.json similarity index 100% rename from website/versioned_sidebars/version-v2.6.0-sidebars.json rename to website/versioned_sidebars/version-v2.8.0-sidebars.json diff --git a/website/versions.json b/website/versions.json index 1e10a413099..00c57e23dba 100644 --- a/website/versions.json +++ b/website/versions.json @@ -1 +1 @@ -["v2.7.0","v2.6.0"] \ No newline at end of file +["v2.8.0","v2.7.0"] \ No newline at end of file From 741558532b6cc209c499460066cc32f09c45802a Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 8 Feb 2024 21:38:24 +1100 Subject: [PATCH 027/369] Revert "Added possibility to specify platform for dev command (#3117)" This reverts commit 4b4fcdd47cb193ff20ea55a689a30e18809d8d9e. --- v2/cmd/wails/build.go | 75 ++++++++++++++---------- v2/cmd/wails/flags/build.go | 32 +++++++++-- v2/cmd/wails/flags/common.go | 98 -------------------------------- v2/cmd/wails/flags/dev.go | 11 +--- v2/cmd/wails/internal/dev/dev.go | 16 ------ v2/pkg/commands/build/build.go | 4 -- website/src/pages/changelog.mdx | 2 +- 7 files changed, 78 insertions(+), 160 deletions(-) diff --git a/v2/cmd/wails/build.go b/v2/cmd/wails/build.go index a71c5d956d5..7364df8bae5 100644 --- a/v2/cmd/wails/build.go +++ b/v2/cmd/wails/build.go @@ -108,7 +108,7 @@ func buildApplication(f *flags.Build) error { {"Tags", "[" + strings.Join(f.GetTags(), ",") + "]"}, {"Race Detector", bool2Str(f.RaceDetector)}, }...) - if len(buildOptions.OutputFile) > 0 && len(f.GetTargets()) == 1 { + if len(buildOptions.OutputFile) > 0 && f.GetTargets().Length() == 1 { tableData = append(tableData, []string{"Output File", f.OutputFilename}) } pterm.DefaultSection.Println("Build Options") @@ -145,11 +145,16 @@ func buildApplication(f *flags.Build) error { // Allows cancelling the build after the first error. It would be nice if targets.Each would support funcs // returning an error. + var targetErr error targets := f.GetTargets() - for _, target := range targets { - if !validPlatformArch.Contains(target.Platform) { - buildOptions.Logger.Println("platform '%s' is not supported - skipping. Supported platforms: %s", target.Platform, validPlatformArch.Join(",")) - continue + targets.Each(func(platform string) { + if targetErr != nil { + return + } + + if !validPlatformArch.Contains(platform) { + buildOptions.Logger.Println("platform '%s' is not supported - skipping. Supported platforms: %s", platform, validPlatformArch.Join(",")) + return } desiredFilename := projectOptions.OutputFilename @@ -158,13 +163,17 @@ func buildApplication(f *flags.Build) error { } desiredFilename = strings.TrimSuffix(desiredFilename, ".exe") - buildOptions.Platform = target.Platform - buildOptions.Arch = target.Arch - + // Calculate platform and arch + platformSplit := strings.Split(platform, "/") + buildOptions.Platform = platformSplit[0] + buildOptions.Arch = f.GetDefaultArch() + if len(platformSplit) > 1 { + buildOptions.Arch = platformSplit[1] + } banner := "Building target: " + buildOptions.Platform + "/" + buildOptions.Arch pterm.DefaultSection.Println(banner) - if f.Upx && target.String() == "darwin/universal" { + if f.Upx && platform == "darwin/universal" { pterm.Warning.Println("Warning: compress flag unsupported for universal binaries. Ignoring.") f.Upx = false } @@ -173,19 +182,22 @@ func buildApplication(f *flags.Build) error { case "linux": if runtime.GOOS != "linux" { pterm.Warning.Println("Crosscompiling to Linux not currently supported.") - continue + return } case "darwin": if runtime.GOOS != "darwin" { pterm.Warning.Println("Crosscompiling to Mac not currently supported.") - continue + return } - if targets.MacTargetsCount() == 2 { + macTargets := targets.Filter(func(platform string) bool { + return strings.HasPrefix(platform, "darwin") + }) + if macTargets.Length() == 2 { buildOptions.BundleName = fmt.Sprintf("%s-%s.app", desiredFilename, buildOptions.Arch) } } - if len(targets) > 1 { + if targets.Length() > 1 { // target filename switch buildOptions.Platform { case "windows": @@ -207,27 +219,32 @@ func buildApplication(f *flags.Build) error { pterm.Warning.Println("obfuscated flag overrides skipbindings flag.") buildOptions.SkipBindings = false } - } - if !f.DryRun { - // Start Time - start := time.Now() + if !f.DryRun { + // Start Time + start := time.Now() - compiledBinary, err := build.Build(buildOptions) - if err != nil { - pterm.Error.Println(err.Error()) - return err - } + compiledBinary, err := build.Build(buildOptions) + if err != nil { + pterm.Error.Println(err.Error()) + targetErr = err + return + } - buildOptions.IgnoreFrontend = true - buildOptions.CleanBinDirectory = false + buildOptions.IgnoreFrontend = true + buildOptions.CleanBinDirectory = false - // Output stats - buildOptions.Logger.Println(fmt.Sprintf("Built '%s' in %s.\n", compiledBinary, time.Since(start).Round(time.Millisecond).String())) + // Output stats + buildOptions.Logger.Println(fmt.Sprintf("Built '%s' in %s.\n", compiledBinary, time.Since(start).Round(time.Millisecond).String())) - outputBinaries[buildOptions.Platform+"/"+buildOptions.Arch] = compiledBinary - } else { - pterm.Info.Println("Dry run: skipped build.") + outputBinaries[buildOptions.Platform+"/"+buildOptions.Arch] = compiledBinary + } else { + pterm.Info.Println("Dry run: skipped build.") + } + }) + + if targetErr != nil { + return targetErr } if f.DryRun { diff --git a/v2/cmd/wails/flags/build.go b/v2/cmd/wails/flags/build.go index 28ef6b9764f..974d9c3adc7 100644 --- a/v2/cmd/wails/flags/build.go +++ b/v2/cmd/wails/flags/build.go @@ -2,10 +2,13 @@ package flags import ( "fmt" + "os" "os/exec" + "runtime" "strings" "github.com/leaanthony/slicer" + "github.com/wailsapp/wails/v2/internal/system" "github.com/wailsapp/wails/v2/pkg/commands/build" "github.com/wailsapp/wails/v2/pkg/commands/buildtags" ) @@ -46,15 +49,29 @@ type Build struct { compilerPath string userTags []string wv2rtstrategy string // WebView2 runtime strategy + defaultArch string // Default architecture } func (b *Build) Default() *Build { - target := defaultTarget() + defaultPlatform := os.Getenv("GOOS") + if defaultPlatform == "" { + defaultPlatform = runtime.GOOS + } + defaultArch := os.Getenv("GOARCH") + if defaultArch == "" { + if system.IsAppleSilicon { + defaultArch = "arm64" + } else { + defaultArch = runtime.GOARCH + } + } result := &Build{ - Platform: target.Platform, + Platform: defaultPlatform + "/" + defaultArch, WebView2: "download", GarbleArgs: "-literals -tiny -seed=random", + + defaultArch: defaultArch, } result.BuildCommon = result.BuildCommon.Default() return result @@ -71,8 +88,11 @@ func (b *Build) GetWebView2Strategy() string { return b.wv2rtstrategy } -func (b *Build) GetTargets() TargetsCollection { - return parseTargets(b.Platform) +func (b *Build) GetTargets() *slicer.StringSlicer { + var targets slicer.StringSlicer + targets.AddSlice(strings.Split(b.Platform, ",")) + targets.Deduplicate() + return &targets } func (b *Build) GetCompilerPath() string { @@ -124,6 +144,10 @@ func (b *Build) GetBuildModeAsString() string { return "production" } +func (b *Build) GetDefaultArch() string { + return b.defaultArch +} + /* _, _ = fmt.Fprintf(w, "Frontend Directory: \t%s\n", projectOptions.GetFrontendDir()) _, _ = fmt.Fprintf(w, "Obfuscated: \t%t\n", buildOptions.Obfuscated) diff --git a/v2/cmd/wails/flags/common.go b/v2/cmd/wails/flags/common.go index 5a81f729d9e..e58eff41192 100644 --- a/v2/cmd/wails/flags/common.go +++ b/v2/cmd/wails/flags/common.go @@ -1,103 +1,5 @@ package flags -import ( - "fmt" - "os" - "runtime" - "strings" - - "github.com/leaanthony/slicer" - "github.com/pterm/pterm" - "github.com/wailsapp/wails/v2/internal/system" -) - type Common struct { NoColour bool `description:"Disable colour in output"` } - -type Target struct { - Platform string - Arch string -} - -func defaultTarget() Target { - defaultPlatform := os.Getenv("GOOS") - if defaultPlatform == "" { - defaultPlatform = runtime.GOOS - } - defaultArch := os.Getenv("GOARCH") - if defaultArch == "" { - if system.IsAppleSilicon { - defaultArch = "arm64" - } else { - defaultArch = runtime.GOARCH - } - } - - return Target{ - Platform: defaultPlatform, - Arch: defaultArch, - } -} - -type TargetsCollection []Target - -func (c TargetsCollection) MacTargetsCount() int { - count := 0 - - for _, t := range c { - if strings.HasPrefix(t.Platform, "darwin") { - count++ - } - } - - return count -} - -func (t Target) String() string { - if t.Arch != "" { - return fmt.Sprintf("%s/%s", t.Platform, t.Arch) - } - - return t.Platform -} - -func parseTargets(platform string) TargetsCollection { - allowedPlatforms := map[string]bool{ - "windows": true, - "linux": true, - "darwin": true, - } - - if !allowedPlatforms[platform] { - pterm.Error.Println("platform argument must be one of 'windows', 'linux', or 'darwin'") - os.Exit(1) - } - - var result []Target - var targets slicer.StringSlicer - - targets.AddSlice(strings.Split(platform, ",")) - targets.Deduplicate() - - targets.Each(func(platform string) { - target := Target{ - Platform: "", - Arch: "", - } - - platformSplit := strings.Split(platform, "/") - - target.Platform = platformSplit[0] - - if len(platformSplit) > 1 { - target.Arch = platformSplit[1] - } else { - target.Arch = defaultTarget().Arch - } - - result = append(result, target) - }) - - return result -} diff --git a/v2/cmd/wails/flags/dev.go b/v2/cmd/wails/flags/dev.go index b581aadb6fd..501450a982e 100644 --- a/v2/cmd/wails/flags/dev.go +++ b/v2/cmd/wails/flags/dev.go @@ -6,6 +6,7 @@ import ( "net/url" "os" "path/filepath" + "runtime" "github.com/samber/lo" "github.com/wailsapp/wails/v2/internal/project" @@ -16,7 +17,6 @@ type Dev struct { BuildCommon AssetDir string `flag:"assetdir" description:"Serve assets from the given directory instead of using the provided asset FS"` - Platform string `flag:"platform" description:"Platform to target"` Extensions string `flag:"e" description:"Extensions to trigger rebuilds (comma separated) eg go"` ReloadDirs string `flag:"reloaddirs" description:"Additional directories to trigger reloads (comma separated)"` Browser bool `flag:"browser" description:"Open the application in a browser"` @@ -38,13 +38,10 @@ type Dev struct { } func (*Dev) Default() *Dev { - target := defaultTarget() result := &Dev{ Extensions: "go", Debounce: 100, - Platform: target.Platform, } - result.BuildCommon = result.BuildCommon.Default() return result } @@ -119,15 +116,13 @@ func (d *Dev) loadAndMergeProjectConfig() error { // GenerateBuildOptions creates a build.Options using the flags func (d *Dev) GenerateBuildOptions() *build.Options { - targets := parseTargets(d.Platform) - result := &build.Options{ OutputType: "dev", Mode: build.Dev, Devtools: true, - Arch: targets[0].Arch, + Arch: runtime.GOARCH, Pack: true, - Platform: targets[0].Platform, + Platform: runtime.GOOS, LDFlags: d.LdFlags, Compiler: d.Compiler, ForceBuild: d.ForceBuild, diff --git a/v2/cmd/wails/internal/dev/dev.go b/v2/cmd/wails/internal/dev/dev.go index 58988bc82ef..02022d12132 100644 --- a/v2/cmd/wails/internal/dev/dev.go +++ b/v2/cmd/wails/internal/dev/dev.go @@ -268,16 +268,6 @@ func runFrontendDevWatcherCommand(frontendDirectory string, devCommand string, d }, viteServerURL, viteVersion, nil } -func isWsl() bool { - version, err := os.ReadFile("/proc/version") - - if err != nil { - return false - } - - return strings.Contains(strings.ToLower(string(version)), "wsl") -} - // restartApp does the actual rebuilding of the application when files change func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process, f *flags.Dev, exitCodeChannel chan int, legacyUseDevServerInsteadofCustomScheme bool) (*process.Process, string, error) { appBinary, err := build.Build(buildOptions) @@ -316,12 +306,6 @@ func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process os.Setenv("devserver", f.DevServer) os.Setenv("frontenddevserverurl", f.FrontendDevServerURL) - if buildOptions.IsWindowsTargetPlatform() && isWsl() { - // In the case of building a Windows executable under WSL, we need to specify this variable with a list of - // variables that will be passed through - os.Setenv("WSLENV", "loglevel/w:frontenddevserverurl/w:devserver/w:assetdir/w") - } - // Start up new binary with correct args newProcess := process.NewProcess(appBinary, args...) err = newProcess.Start(exitCodeChannel) diff --git a/v2/pkg/commands/build/build.go b/v2/pkg/commands/build/build.go index a2b8ffcb213..5bc3051a4a6 100644 --- a/v2/pkg/commands/build/build.go +++ b/v2/pkg/commands/build/build.go @@ -71,10 +71,6 @@ type Options struct { SkipBindings bool // Skip binding generation } -func (o *Options) IsWindowsTargetPlatform() bool { - return strings.Contains(strings.ToLower(o.Platform), "windows") -} - // Build the project! func Build(options *Options) (string, error) { // Extract logger diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index 2a2ebeaf778..b230d367a53 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -17,7 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## v2.8.0 - 2024-02-08 ### Added -- Added option to specify platform for dev command. Thanks to [@pylotlight](https://github.com/pylotlight) for the fix ([#3117](https://github.com/wailsapp/wails/pull/3117)). Based on the work of [@evsign](https://github.com/evsign) in [Draft PR](https://github.com/wailsapp/wails/pull/2724). + - Added windows options supports `DisablePinchZoom` configuration. Added by @tuuzed in [PR](https://github.com/wailsapp/wails/pull/3115) - Add Apple Silicon hardware detection to `wails doctor`. Changed by @almas1992 in [PR](https://github.com/wailsapp/wails/pull/3129) - Remove quarantine attribute on macOS binaries. Changed by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/3118) From 1c8e2ee8fe6df6948757f5d0e480aa729aaca590 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 21:04:35 +1100 Subject: [PATCH 028/369] chore: update sponsors.svg (#3241) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index f077852c289..2e85cce46f4 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -76,7 +76,7 @@ text { igops - + Buying Coffee From 1957e2e86c37c4d7be0e2b5018b84af7d907d253 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 14 Feb 2024 18:09:12 +1100 Subject: [PATCH 029/369] Create SECURITY.md --- SECURITY.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000000..72ef20b54c8 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,38 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 2.x.x | :white_check_mark: | +| 3.0.x-alpha | :x: | + + +## Reporting a Vulnerability + +If you believe you have found a security vulnerability in our project, we encourage you to let us know right away. +We will investigate all legitimate reports and do our best to quickly fix the problem. + +Before reporting though, please review our security policy below. + +### How to Report + +To report a security vulnerability, please send an email to `security@wails.io`. If possible, please include as much information as possible. +This may include steps to reproduce, impact of the vulnerability, and anything else you believe would help us understand the problem. +**Please do not include any sensitive or personal information in your report**. + +### What to Expect + +When you report a vulnerability, here's what you can expect: + +- **Acknowledgement**: We will acknowledge your email within 48 hours, and you'll receive a more detailed response to your email within 72 hours indicating the next steps in handling your report. + +- **Updates**: After the initial reply to your report, our team will keep you informed of the progress being made towards a fix and full announcement. These updates will be sent at least once a week. + +- **Confidentiality**: We will maintain strict confidentiality of your report until the security issue is resolved. + +- **Issue Resolution**: If the issue is confirmed, we will release a patch as soon as possible depending on complexity of the fix. + +- **Recognition**: We recognize and appreciate every individual who helps us identify and fix vulnerabilities in our project. While we do not currently have a bounty program, we would be happy to publicly acknowledge your responsible disclosure. + +We strive to make Wails safe for everyone, and we greatly appreciate the assistance of security researchers and users in helping us identify and fix vulnerabilities. Thank you for your contribution to the security of this project. From d899621351bbd05e3b7a0fa718fe61c9ceabbf5b Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 14 Feb 2024 18:15:24 +1100 Subject: [PATCH 030/369] Update SECURITY.md --- SECURITY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index 72ef20b54c8..cb096f8727a 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -17,7 +17,7 @@ Before reporting though, please review our security policy below. ### How to Report -To report a security vulnerability, please send an email to `security@wails.io`. If possible, please include as much information as possible. +To report a security vulnerability, please use GitHub's [private vulnerability reporting](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability) feature. If possible, please include as much information as possible. This may include steps to reproduce, impact of the vulnerability, and anything else you believe would help us understand the problem. **Please do not include any sensitive or personal information in your report**. From 9c3f91bb48e49963b3a3c9afc6574c805e9b19b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Feb 2024 18:21:54 +1100 Subject: [PATCH 031/369] Bump the npm_and_yarn group across 3 directories with 1 update (#3257) Bumps the npm_and_yarn group with 1 update in the /scripts/sponsors directory: [semver](https://github.com/npm/node-semver). Bumps the npm_and_yarn group with 1 update in the /v2/internal/frontend/runtime directory: [semver](https://github.com/npm/node-semver). Updates `semver` from 7.5.4 to 7.6.0 - [Release notes](https://github.com/npm/node-semver/releases) - [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-semver/compare/v7.5.4...v7.6.0) Updates `semver` from 5.7.1 to 5.7.2 - [Release notes](https://github.com/npm/node-semver/releases) - [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-semver/compare/v7.5.4...v7.6.0) --- updated-dependencies: - dependency-name: semver dependency-type: indirect dependency-group: npm_and_yarn-security-group - dependency-name: semver dependency-type: indirect dependency-group: npm_and_yarn-security-group ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- scripts/sponsors/package-lock.json | 6 +++--- v2/internal/frontend/runtime/package-lock.json | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/sponsors/package-lock.json b/scripts/sponsors/package-lock.json index 6fa8f99fcc2..f0d773a762f 100644 --- a/scripts/sponsors/package-lock.json +++ b/scripts/sponsors/package-lock.json @@ -1523,9 +1523,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, diff --git a/v2/internal/frontend/runtime/package-lock.json b/v2/internal/frontend/runtime/package-lock.json index f6535549db6..daf6ecf28b6 100644 --- a/v2/internal/frontend/runtime/package-lock.json +++ b/v2/internal/frontend/runtime/package-lock.json @@ -1541,9 +1541,9 @@ "dev": true }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "bin": { "semver": "bin/semver" @@ -3067,9 +3067,9 @@ "dev": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true }, "shebang-command": { From 65251cdafac9e9b0a61823e48961f63c7ca87a38 Mon Sep 17 00:00:00 2001 From: stffabi Date: Wed, 14 Feb 2024 08:19:00 +0100 Subject: [PATCH 032/369] [v3, assetServer] Remove fs.FS from options and always use a http.Handler --- v3/examples/binding/main.go | 2 +- v3/examples/contextmenus/main.go | 2 +- v3/examples/dev/main.go | 2 +- v3/examples/drag-n-drop/main.go | 2 +- v3/examples/events/main.go | 2 +- v3/examples/frameless/main.go | 2 +- v3/examples/oauth/main.go | 7 +- v3/examples/plugins/main.go | 2 +- v3/examples/screen/main.go | 2 +- v3/examples/server/main.go | 2 +- v3/examples/wml/main.go | 2 +- .../{assethandler.go => asset_fileserver.go} | 109 ++++++------------ v3/internal/assetserver/assetserver.go | 50 ++++---- v3/internal/assetserver/assetserver_dev.go | 5 +- v3/internal/assetserver/build_dev.go | 85 +++----------- v3/internal/assetserver/build_production.go | 9 +- v3/internal/assetserver/common.go | 22 ++++ v3/internal/assetserver/fs.go | 6 +- v3/internal/assetserver/options.go | 21 +--- v3/pkg/application/application.go | 10 +- v3/pkg/application/options_application.go | 27 +++-- 21 files changed, 147 insertions(+), 224 deletions(-) rename v3/internal/assetserver/{assethandler.go => asset_fileserver.go} (52%) diff --git a/v3/examples/binding/main.go b/v3/examples/binding/main.go index 15a448bbd32..aa0fc8d3daf 100644 --- a/v3/examples/binding/main.go +++ b/v3/examples/binding/main.go @@ -17,7 +17,7 @@ func main() { &GreetService{}, }, Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/v3/examples/contextmenus/main.go b/v3/examples/contextmenus/main.go index 4cb7977d08b..1a47cb4056b 100644 --- a/v3/examples/contextmenus/main.go +++ b/v3/examples/contextmenus/main.go @@ -17,7 +17,7 @@ func main() { Name: "Context Menu Demo", Description: "A demo of the Context Menu API", Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/v3/examples/dev/main.go b/v3/examples/dev/main.go index acfcc8ba6b4..478702f5640 100644 --- a/v3/examples/dev/main.go +++ b/v3/examples/dev/main.go @@ -16,7 +16,7 @@ func main() { Name: "dev", Description: "A demo of using raw HTML & CSS", Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/v3/examples/drag-n-drop/main.go b/v3/examples/drag-n-drop/main.go index a0feae58646..abaaa04a2ed 100644 --- a/v3/examples/drag-n-drop/main.go +++ b/v3/examples/drag-n-drop/main.go @@ -18,7 +18,7 @@ func main() { Name: "Drag-n-drop Demo", Description: "A demo of the Drag-n-drop API", Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/v3/examples/events/main.go b/v3/examples/events/main.go index 8ec5a2bc804..1fe96a96171 100644 --- a/v3/examples/events/main.go +++ b/v3/examples/events/main.go @@ -19,7 +19,7 @@ func main() { Name: "Events Demo", Description: "A demo of the Events API", Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/v3/examples/frameless/main.go b/v3/examples/frameless/main.go index 684c7eaf3e5..c59b670257e 100644 --- a/v3/examples/frameless/main.go +++ b/v3/examples/frameless/main.go @@ -17,7 +17,7 @@ func main() { Name: "Frameless Demo", Description: "A demo of frameless windows", Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/v3/examples/oauth/main.go b/v3/examples/oauth/main.go index 449dbab9620..14818c47f35 100644 --- a/v3/examples/oauth/main.go +++ b/v3/examples/oauth/main.go @@ -3,12 +3,13 @@ package main import ( "embed" _ "embed" + "log" + "os" + "github.com/markbates/goth" "github.com/markbates/goth/providers/github" "github.com/wailsapp/wails/v3/pkg/application" "github.com/wailsapp/wails/v3/plugins/oauth" - "log" - "os" ) //go:embed assets @@ -34,7 +35,7 @@ func main() { ApplicationShouldTerminateAfterLastWindowClosed: true, }, Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Plugins: map[string]application.Plugin{ "github.com/wailsapp/wails/v3/plugins/oauth": oAuthPlugin, diff --git a/v3/examples/plugins/main.go b/v3/examples/plugins/main.go index e113a3d1638..99f273d00e9 100644 --- a/v3/examples/plugins/main.go +++ b/v3/examples/plugins/main.go @@ -46,7 +46,7 @@ func main() { "start_at_login": start_at_login.NewPlugin(start_at_login.Config{}), }, Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, }) diff --git a/v3/examples/screen/main.go b/v3/examples/screen/main.go index 3f80e210609..32c04bafd90 100644 --- a/v3/examples/screen/main.go +++ b/v3/examples/screen/main.go @@ -26,7 +26,7 @@ func main() { WebviewBrowserPath: "", }, Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, }) diff --git a/v3/examples/server/main.go b/v3/examples/server/main.go index f9d8633ed70..ca683ed4e17 100644 --- a/v3/examples/server/main.go +++ b/v3/examples/server/main.go @@ -30,7 +30,7 @@ func main() { }), }, Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, }) go func() { diff --git a/v3/examples/wml/main.go b/v3/examples/wml/main.go index 84f48a7c948..aa7a54fb390 100644 --- a/v3/examples/wml/main.go +++ b/v3/examples/wml/main.go @@ -20,7 +20,7 @@ func main() { ApplicationShouldTerminateAfterLastWindowClosed: true, }, Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, }) diff --git a/v3/internal/assetserver/assethandler.go b/v3/internal/assetserver/asset_fileserver.go similarity index 52% rename from v3/internal/assetserver/assethandler.go rename to v3/internal/assetserver/asset_fileserver.go index 253dd269471..d32bfd8f03c 100644 --- a/v3/internal/assetserver/assethandler.go +++ b/v3/internal/assetserver/asset_fileserver.go @@ -2,12 +2,13 @@ package assetserver import ( "bytes" + "context" "embed" "errors" "fmt" "io" + "io/fs" iofs "io/fs" - "log/slog" "net/http" "os" "path" @@ -18,91 +19,53 @@ const ( indexHTML = "index.html" ) -type assetHandler struct { - fs iofs.FS - handler http.Handler - - logger *slog.Logger - - retryMissingFiles bool +type assetFileServer struct { + fs iofs.FS + err error } -func NewDefaultAssetHandler(options *Options) (http.Handler, error) { - - vfs := options.Assets - if vfs != nil { - if _, err := vfs.Open("."); err != nil { - return nil, err - } - - subDir, err := FindPathToFile(vfs, indexHTML) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - msg := "no `index.html` could be found in your Assets fs.FS" - if embedFs, isEmbedFs := vfs.(embed.FS); isEmbedFs { - rootFolder, _ := FindEmbedRootPath(embedFs) - msg += fmt.Sprintf(", please make sure the embedded directory '%s' is correct and contains your assets", rootFolder) - } - - return nil, fmt.Errorf(msg) +func newAssetFileServerFS(vfs fs.FS) http.Handler { + subDir, err := findPathToFile(vfs, indexHTML) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + msg := "no `index.html` could be found in your Assets fs.FS" + if embedFs, isEmbedFs := vfs.(embed.FS); isEmbedFs { + rootFolder, _ := findEmbedRootPath(embedFs) + msg += fmt.Sprintf(", please make sure the embedded directory '%s' is correct and contains your assets", rootFolder) } - return nil, err + err = fmt.Errorf(msg) } - + } else { vfs, err = iofs.Sub(vfs, path.Clean(subDir)) - if err != nil { - return nil, err - } - } - - var result http.Handler = &assetHandler{ - fs: vfs, - handler: options.Handler, - logger: options.Logger, - } - - if middleware := options.Middleware; middleware != nil { - result = middleware(result) } - return result, nil + return &assetFileServer{fs: vfs, err: err} } -func (d *assetHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { +func (d *assetFileServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + ctx := req.Context() url := req.URL.Path - handler := d.handler - if strings.EqualFold(req.Method, http.MethodGet) { - filename := path.Clean(strings.TrimPrefix(url, "/")) - - d.logInfo("Handling request", "url", url, "file", filename) - if err := d.serveFSFile(rw, req, filename); err != nil { - if os.IsNotExist(err) { - if handler != nil { - d.logInfo("File not found. Deferring to AssetHandler", "filename", filename, "url", url) - handler.ServeHTTP(rw, req) - err = nil - } else { - rw.WriteHeader(http.StatusNotFound) - err = nil - } - } - if err != nil { - d.logError("Unable to handle request '%s': %s", url, err) - http.Error(rw, err.Error(), http.StatusInternalServerError) - } + err := d.err + if err == nil { + filename := path.Clean(strings.TrimPrefix(url, "/")) + d.logInfo(ctx, "Handling request", "url", url, "file", filename) + err = d.serveFSFile(rw, req, filename) + if os.IsNotExist(err) { + rw.WriteHeader(http.StatusNotFound) + return } - } else if handler != nil { - d.logInfo("Non-GET request. Deferring to AssetHandler", "url", url) - handler.ServeHTTP(rw, req) - } else { - rw.WriteHeader(http.StatusMethodNotAllowed) + } + + if err != nil { + d.logError(ctx, "Unable to handle request", "url", url, "err", err) + http.Error(rw, err.Error(), http.StatusInternalServerError) } } // serveFile will try to load the file from the fs.FS and write it to the response -func (d *assetHandler) serveFSFile(rw http.ResponseWriter, req *http.Request, filename string) error { +func (d *assetFileServer) serveFSFile(rw http.ResponseWriter, req *http.Request, filename string) error { if d.fs == nil { return os.ErrNotExist } @@ -182,10 +145,10 @@ func (d *assetHandler) serveFSFile(rw http.ResponseWriter, req *http.Request, fi return err } -func (d *assetHandler) logInfo(message string, args ...interface{}) { - d.logger.Debug("[AssetHandler] "+message, args...) +func (d *assetFileServer) logInfo(ctx context.Context, message string, args ...interface{}) { + logInfo(ctx, "[AssetFileServerFS] "+message, args...) } -func (d *assetHandler) logError(message string, args ...interface{}) { - d.logger.Error("[AssetHandler] "+message, args...) +func (d *assetFileServer) logError(ctx context.Context, message string, args ...interface{}) { + logError(ctx, "[AssetFileServerFS] "+message, args...) } diff --git a/v3/internal/assetserver/assetserver.go b/v3/internal/assetserver/assetserver.go index 08947e92ec3..415f33cf615 100644 --- a/v3/internal/assetserver/assetserver.go +++ b/v3/internal/assetserver/assetserver.go @@ -6,7 +6,6 @@ import ( "net" "net/http" "net/http/httptest" - "net/http/httputil" "net/url" "path" "strings" @@ -29,34 +28,43 @@ type RuntimeHandler interface { type AssetServer struct { options *Options - handler http.Handler - wsHandler *httputil.ReverseProxy + handler http.Handler pluginScripts map[string]string - devServerURL string - assetServerWebView } func NewAssetServer(options *Options) (*AssetServer, error) { - result := &AssetServer{ - options: options, + result := &AssetServer{options: options} + + userHandler := options.Handler + if userHandler == nil { + userHandler = http.NotFoundHandler() } - var err error - result.handler, err = result.setupHandler() - if err != nil { - return nil, err + handler := http.Handler( + http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + result.serveHTTP(w, r, userHandler) + })) + + if middleware := options.Middleware; middleware != nil { + handler = middleware(handler) } + result.handler = handler + return result, nil } func (a *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { start := time.Now() wrapped := &contentTypeSniffer{rw: rw} - a.serveHTTP(wrapped, req) + + req = req.WithContext(contextWithLogger(req.Context(), a.options.Logger)) + a.handler.ServeHTTP(wrapped, req) + a.options.Logger.Info( "Asset Request:", "windowName", req.Header.Get(webViewRequestHeaderWindowName), @@ -68,17 +76,11 @@ func (a *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { ) } -func (a *AssetServer) serveHTTP(rw http.ResponseWriter, req *http.Request) { - - if a.wsHandler != nil { - a.wsHandler.ServeHTTP(rw, req) +func (a *AssetServer) serveHTTP(rw http.ResponseWriter, req *http.Request, userHandler http.Handler) { + if isWebSocket(req) { + // WebSockets are not supported by the AssetServer + rw.WriteHeader(http.StatusNotImplemented) return - } else { - if isWebSocket(req) { - // WebSockets are not supported by the AssetServer - rw.WriteHeader(http.StatusNotImplemented) - return - } } header := rw.Header() @@ -91,7 +93,7 @@ func (a *AssetServer) serveHTTP(rw http.ResponseWriter, req *http.Request) { switch path { case "", "/", "/index.html": recorder := httptest.NewRecorder() - a.handler.ServeHTTP(recorder, req) + userHandler.ServeHTTP(recorder, req) for k, v := range recorder.Result().Header { header[k] = v } @@ -126,7 +128,7 @@ func (a *AssetServer) serveHTTP(rw http.ResponseWriter, req *http.Request) { if script, ok := a.pluginScripts[path]; ok { a.writeBlob(rw, path, []byte(script)) } else { - a.handler.ServeHTTP(rw, req) + userHandler.ServeHTTP(rw, req) return } } diff --git a/v3/internal/assetserver/assetserver_dev.go b/v3/internal/assetserver/assetserver_dev.go index 6b5af30a85d..61f5a6b5c8b 100644 --- a/v3/internal/assetserver/assetserver_dev.go +++ b/v3/internal/assetserver/assetserver_dev.go @@ -4,12 +4,11 @@ package assetserver func (a *AssetServer) LogDetails() { var info = []any{ - "assetsFS", a.options.Assets != nil, "middleware", a.options.Middleware != nil, "handler", a.options.Handler != nil, } - if a.devServerURL != "" { - info = append(info, "devServerURL", a.devServerURL) + if devServerURL := GetDevServerURL(); devServerURL != "" { + info = append(info, "devServerURL", devServerURL) } a.options.Logger.Info("AssetServer Info:", info...) } diff --git a/v3/internal/assetserver/build_dev.go b/v3/internal/assetserver/build_dev.go index cd84afb355d..dda03f125fe 100644 --- a/v3/internal/assetserver/build_dev.go +++ b/v3/internal/assetserver/build_dev.go @@ -4,8 +4,7 @@ package assetserver import ( _ "embed" - "errors" - "fmt" + "io/fs" "net/http" "net/http/httputil" "net/url" @@ -19,83 +18,29 @@ func defaultIndexHTML() []byte { return defaultHTML } -func (a *AssetServer) setupHandler() (http.Handler, error) { - - // Do we have an external dev server URL? - a.devServerURL = GetDevServerURL() - if a.devServerURL == "" { - return NewDefaultAssetHandler(a.options) +func NewAssetFileServer(vfs fs.FS) http.Handler { + devServerURL := GetDevServerURL() + if devServerURL == "" { + return newAssetFileServerFS(vfs) } - // Parse the URL - parsedURL, err := url.Parse(a.devServerURL) + parsedURL, err := url.Parse(devServerURL) if err != nil { - return nil, fmt.Errorf("invalid FRONTEND_DEVSERVER_URL. Should be valid URL: %s", err.Error()) - } - - baseHandler := a.options.Handler - - errSkipProxy := fmt.Errorf("skip proxying") - - proxy := httputil.NewSingleHostReverseProxy(parsedURL) - baseDirector := proxy.Director - proxy.Director = func(r *http.Request) { - baseDirector(r) - if a.options.Logger != nil { - a.options.Logger.Debug("ExternalAssetHandler: loading", "url", r.URL) - } - } - - proxy.ModifyResponse = func(res *http.Response) error { - if baseHandler == nil { - return nil - } + return http.HandlerFunc( + func(rw http.ResponseWriter, req *http.Request) { + logError(req.Context(), "[ExternalAssetHandler] Invalid FRONTEND_DEVSERVER_URL. Should be valid URL", "error", err.Error()) + http.Error(rw, err.Error(), http.StatusInternalServerError) + }) - if res.StatusCode == http.StatusSwitchingProtocols { - return nil - } - - if res.StatusCode == http.StatusNotFound || res.StatusCode == http.StatusMethodNotAllowed { - return errSkipProxy - } - - return nil } + proxy := httputil.NewSingleHostReverseProxy(parsedURL) proxy.ErrorHandler = func(rw http.ResponseWriter, r *http.Request, err error) { - if baseHandler != nil && errors.Is(err, errSkipProxy) { - if a.options.Logger != nil { - a.options.Logger.Debug("ExternalAssetHandler: Loading file failed, using original AssetHandler", "url", r.URL) - } - baseHandler.ServeHTTP(rw, r) - } else { - if a.options.Logger != nil { - a.options.Logger.Error("ExternalAssetHandler: Proxy error", "error", err.Error()) - } - rw.WriteHeader(http.StatusBadGateway) - } - } - - var result http.Handler = http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - if req.Method == http.MethodGet { - proxy.ServeHTTP(rw, req) - return - } - - if baseHandler != nil { - baseHandler.ServeHTTP(rw, req) - return - } - - rw.WriteHeader(http.StatusMethodNotAllowed) - }) - - if middleware := a.options.Middleware; middleware != nil { - result = middleware(result) + logError(r.Context(), "[ExternalAssetHandler] Proxy error", "error", err.Error()) + rw.WriteHeader(http.StatusBadGateway) } - return result, nil + return proxy } func GetDevServerURL() string { diff --git a/v3/internal/assetserver/build_production.go b/v3/internal/assetserver/build_production.go index 0f858faf91e..b5bba6b1234 100644 --- a/v3/internal/assetserver/build_production.go +++ b/v3/internal/assetserver/build_production.go @@ -2,14 +2,17 @@ package assetserver -import "net/http" +import ( + "io/fs" + "net/http" +) func defaultIndexHTML() []byte { return []byte{} } -func (a *AssetServer) setupHandler() (http.Handler, error) { - return NewDefaultAssetHandler(a.options) +func NewAssetFileServer(vfs fs.FS) http.Handler { + return newAssetFileServerFS(vfs) } func GetDevServerURL() string { diff --git a/v3/internal/assetserver/common.go b/v3/internal/assetserver/common.go index 484858cfa10..109c228be53 100644 --- a/v3/internal/assetserver/common.go +++ b/v3/internal/assetserver/common.go @@ -2,8 +2,10 @@ package assetserver import ( "bytes" + "context" "fmt" "io" + "log/slog" "net/http" "strings" ) @@ -20,6 +22,10 @@ const ( WailsUserAgentValue = "wails.io" ) +var ( + assetServerLogger = struct{}{} +) + func serveFile(rw http.ResponseWriter, filename string, blob []byte) error { header := rw.Header() header.Set(HeaderContentLength, fmt.Sprintf("%d", len(blob))) @@ -37,3 +43,19 @@ func isWebSocket(req *http.Request) bool { upgrade := req.Header.Get(HeaderUpgrade) return strings.EqualFold(upgrade, "websocket") } + +func contextWithLogger(ctx context.Context, logger *slog.Logger) context.Context { + return context.WithValue(ctx, assetServerLogger, logger) +} + +func logInfo(ctx context.Context, message string, args ...interface{}) { + if logger, _ := ctx.Value(assetServerLogger).(*slog.Logger); logger != nil { + logger.Info(message, args...) + } +} + +func logError(ctx context.Context, message string, args ...interface{}) { + if logger, _ := ctx.Value(assetServerLogger).(*slog.Logger); logger != nil { + logger.Error(message, args...) + } +} diff --git a/v3/internal/assetserver/fs.go b/v3/internal/assetserver/fs.go index 65f24ed787f..4d8aad579a8 100644 --- a/v3/internal/assetserver/fs.go +++ b/v3/internal/assetserver/fs.go @@ -10,8 +10,8 @@ import ( "strings" ) -// FindEmbedRootPath finds the root path in the embed FS. It's the directory which contains all the files. -func FindEmbedRootPath(fileSystem embed.FS) (string, error) { +// findEmbedRootPath finds the root path in the embed FS. It's the directory which contains all the files. +func findEmbedRootPath(fileSystem embed.FS) (string, error) { stopErr := fmt.Errorf("files or multiple dirs found") fPath := "" @@ -39,7 +39,7 @@ func FindEmbedRootPath(fileSystem embed.FS) (string, error) { return fPath, nil } -func FindPathToFile(fileSystem fs.FS, file string) (string, error) { +func findPathToFile(fileSystem fs.FS, file string) (string, error) { stat, _ := fs.Stat(fileSystem, file) if stat != nil { return ".", nil diff --git a/v3/internal/assetserver/options.go b/v3/internal/assetserver/options.go index f199a9b0d92..60c43e26907 100644 --- a/v3/internal/assetserver/options.go +++ b/v3/internal/assetserver/options.go @@ -2,26 +2,13 @@ package assetserver import ( "fmt" - "io/fs" "log/slog" "net/http" ) // Options defines the configuration of the AssetServer. type Options struct { - // Assets defines the static assets to be used. A GET request is first tried to be served from this Assets. If the Assets returns - // `os.ErrNotExist` for that file, the request handling will fallback to the Handler and tries to serve the GET - // request from it. - // - // If set to nil, all GET requests will be forwarded to Handler. - Assets fs.FS - - // Handler will be called for every GET request that can't be served from Assets, due to `os.ErrNotExist`. Furthermore all - // non GET requests will always be served from this Handler. - // - // If not defined, the result is the following in cases where the Handler would have been called: - // GET request: `http.StatusNotFound` - // Other request: `http.StatusMethodNotAllowed` + // Handler which serves all the content to the WebView. Handler http.Handler // Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default @@ -29,6 +16,8 @@ type Options struct { // The Middleware is called to build a new `http.Handler` used by the AssetSever and it also receives the default // handler used by the AssetServer as an argument. // + // This middleware injects itself before any of Wails internal middlewares. + // // If not defined, the default AssetServer request chain is executed. // // Multiple Middlewares can be chained together with: @@ -50,8 +39,8 @@ type Options struct { // Validate the options func (o Options) Validate() error { - if o.Assets == nil && o.Handler == nil && o.Middleware == nil { - return fmt.Errorf("AssetServer options invalid: either Assets, Handler or Middleware must be set") + if o.Handler == nil && o.Middleware == nil { + return fmt.Errorf("AssetServer options invalid: either Handler or Middleware must be set") } return nil diff --git a/v3/pkg/application/application.go b/v3/pkg/application/application.go index 319acd6b81a..60fd64e5f9e 100644 --- a/v3/pkg/application/application.go +++ b/v3/pkg/application/application.go @@ -3,9 +3,6 @@ package application import ( "embed" "encoding/json" - "github.com/pkg/browser" - "github.com/samber/lo" - "github.com/wailsapp/wails/v3/internal/signal" "io" "log" "log/slog" @@ -15,6 +12,10 @@ import ( "strconv" "sync" + "github.com/pkg/browser" + "github.com/samber/lo" + "github.com/wailsapp/wails/v3/internal/signal" + "github.com/wailsapp/wails/v3/internal/assetserver" "github.com/wailsapp/wails/v3/internal/assetserver/webview" "github.com/wailsapp/wails/v3/internal/capabilities" @@ -29,7 +30,7 @@ var globalApplication *App // AlphaAssets is the default assets for the alpha application var AlphaAssets = AssetOptions{ - FS: alphaAssets, + Handler: AssetFileServerFS(alphaAssets), } func init() { @@ -76,7 +77,6 @@ func New(appOptions Options) *App { result.Events = NewWailsEventProcessor(result.dispatchEventToWindows) opts := &assetserver.Options{ - Assets: appOptions.Assets.FS, Handler: appOptions.Assets.Handler, Middleware: assetserver.Middleware(appOptions.Assets.Middleware), Logger: result.Logger, diff --git a/v3/pkg/application/options_application.go b/v3/pkg/application/options_application.go index d005dfb2a7b..10bf75188eb 100644 --- a/v3/pkg/application/options_application.go +++ b/v3/pkg/application/options_application.go @@ -4,6 +4,8 @@ import ( "io/fs" "log/slog" "net/http" + + "github.com/wailsapp/wails/v3/internal/assetserver" ) type Options struct { @@ -68,26 +70,16 @@ type Options struct { // AssetOptions defines the configuration of the AssetServer. type AssetOptions struct { - // FS defines the static assets to be used. A GET request is first tried to be served from this FS. If the FS returns - // `os.ErrNotExist` for that file, the request handling will fallback to the Handler and tries to serve the GET - // request from it. - // - // If set to nil, all GET requests will be forwarded to Handler. - FS fs.FS - - // Handler will be called for every GET request that can't be served from FS, due to `os.ErrNotExist`. Furthermore all - // non GET requests will always be served from this Handler. - // - // If not defined, the result is the following in cases where the Handler would have been called: - // GET request: `http.StatusNotFound` - // Other request: `http.StatusMethodNotAllowed` + // Handler which serves all the content to the WebView. Handler http.Handler - // Middleware is HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default + // Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default // request handler dynamically, e.g. implement specialized Routing etc. // The Middleware is called to build a new `http.Handler` used by the AssetSever and it also receives the default // handler used by the AssetServer as an argument. // + // This middleware injects itself before any of Wails internal middlewares. + // // If not defined, the default AssetServer request chain is executed. // // Multiple Middlewares can be chained together with: @@ -112,3 +104,10 @@ func ChainMiddleware(middleware ...Middleware) Middleware { return h } } + +// AssetFileServerFS returns a http handler which serves the assets from the fs.FS. +// If an external devserver has been provided 'FRONTEND_DEVSERVER_URL' the files are being served +// from the external server, ignoring the `assets`. +func AssetFileServerFS(assets fs.FS) http.Handler { + return assetserver.NewAssetFileServer(assets) +} From 723dd976b4004b20ca2f7142831027049bbe4ef2 Mon Sep 17 00:00:00 2001 From: stffabi Date: Thu, 15 Feb 2024 07:27:31 +0100 Subject: [PATCH 033/369] [v3, assetServer] Use middlewares for runtime, caps and falgs instead of having the implementation in the assetserver --- v3/internal/assetserver/assetserver.go | 21 +----------- v3/internal/assetserver/common.go | 2 +- v3/internal/assetserver/options.go | 9 ----- v3/pkg/application/application.go | 46 +++++++++++++++++--------- 4 files changed, 33 insertions(+), 45 deletions(-) diff --git a/v3/internal/assetserver/assetserver.go b/v3/internal/assetserver/assetserver.go index 415f33cf615..4acddcddf3e 100644 --- a/v3/internal/assetserver/assetserver.go +++ b/v3/internal/assetserver/assetserver.go @@ -13,10 +13,6 @@ import ( ) const ( - runtimePath = "/wails/runtime" - capabilitiesPath = "/wails/capabilities" - flagsPath = "/wails/flags" - webViewRequestHeaderWindowId = "x-wails-window-id" webViewRequestHeaderWindowName = "x-wails-window-name" ) @@ -107,21 +103,7 @@ func (a *AssetServer) serveHTTP(rw http.ResponseWriter, req *http.Request, userH default: rw.WriteHeader(recorder.Code) - } - return - - case capabilitiesPath: - var data = a.options.GetCapabilities() - a.writeBlob(rw, path, data) - - case flagsPath: - var data = a.options.GetFlags() - a.writeBlob(rw, path, data) - - case runtimePath: - a.options.RuntimeHandler.ServeHTTP(rw, req) - return default: // Check if this is a plugin script @@ -129,13 +111,12 @@ func (a *AssetServer) serveHTTP(rw http.ResponseWriter, req *http.Request, userH a.writeBlob(rw, path, []byte(script)) } else { userHandler.ServeHTTP(rw, req) - return } } } func (a *AssetServer) writeBlob(rw http.ResponseWriter, filename string, blob []byte) { - err := serveFile(rw, filename, blob) + err := ServeFile(rw, filename, blob) if err != nil { a.serveError(rw, err, "Unable to write content %s", filename) } diff --git a/v3/internal/assetserver/common.go b/v3/internal/assetserver/common.go index 109c228be53..2fe219f248b 100644 --- a/v3/internal/assetserver/common.go +++ b/v3/internal/assetserver/common.go @@ -26,7 +26,7 @@ var ( assetServerLogger = struct{}{} ) -func serveFile(rw http.ResponseWriter, filename string, blob []byte) error { +func ServeFile(rw http.ResponseWriter, filename string, blob []byte) error { header := rw.Header() header.Set(HeaderContentLength, fmt.Sprintf("%d", len(blob))) if mimeType := header.Get(HeaderContentType); mimeType == "" { diff --git a/v3/internal/assetserver/options.go b/v3/internal/assetserver/options.go index 60c43e26907..987eae7b5ae 100644 --- a/v3/internal/assetserver/options.go +++ b/v3/internal/assetserver/options.go @@ -26,15 +26,6 @@ type Options struct { // Logger is the logger used by the AssetServer. If not defined, no logging will be done. Logger *slog.Logger - - // RuntimeHandler is the handler used for the runtime calls. - RuntimeHandler http.Handler - - // GetCapabilities returns the capabilities of the runtime - GetCapabilities func() []byte - - // GetFlags returns the application flags - GetFlags func() []byte } // Validate the options diff --git a/v3/pkg/application/application.go b/v3/pkg/application/application.go index 60fd64e5f9e..03b9d19d7bf 100644 --- a/v3/pkg/application/application.go +++ b/v3/pkg/application/application.go @@ -76,22 +76,38 @@ func New(appOptions Options) *App { result.Events = NewWailsEventProcessor(result.dispatchEventToWindows) + messageProc := NewMessageProcessor(result.Logger) opts := &assetserver.Options{ - Handler: appOptions.Assets.Handler, - Middleware: assetserver.Middleware(appOptions.Assets.Middleware), - Logger: result.Logger, - RuntimeHandler: NewMessageProcessor(result.Logger), - GetCapabilities: func() []byte { - return globalApplication.capabilities.AsBytes() - }, - GetFlags: func() []byte { - updatedOptions := result.impl.GetFlags(appOptions) - flags, err := json.Marshal(updatedOptions) - if err != nil { - log.Fatal("Invalid flags provided to application: ", err.Error()) - } - return flags - }, + Handler: appOptions.Assets.Handler, + Middleware: assetserver.ChainMiddleware( + func(next http.Handler) http.Handler { + if m := appOptions.Assets.Middleware; m != nil { + return m(next) + } + return next + }, + func(next http.Handler) http.Handler { + return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + path := req.URL.Path + switch path { + case "/wails/runtime": + messageProc.ServeHTTP(rw, req) + case "/wails/capabilities": + assetserver.ServeFile(rw, path, globalApplication.capabilities.AsBytes()) + case "/wails/flags": + updatedOptions := result.impl.GetFlags(appOptions) + flags, err := json.Marshal(updatedOptions) + if err != nil { + log.Fatal("Invalid flags provided to application: ", err.Error()) + } + assetserver.ServeFile(rw, path, flags) + default: + next.ServeHTTP(rw, req) + } + }) + }, + ), + Logger: result.Logger, } if appOptions.Assets.DisableLogging { From 1956f95f9f9368e0606201dd5e7347779d704067 Mon Sep 17 00:00:00 2001 From: stffabi Date: Fri, 16 Feb 2024 08:04:16 +0100 Subject: [PATCH 034/369] [templates] Update templates to latest assetserver options --- v3/internal/templates/_base/default/main.go.tmpl | 2 +- v3/internal/templates/_common/main.go.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/v3/internal/templates/_base/default/main.go.tmpl b/v3/internal/templates/_base/default/main.go.tmpl index 7edc1c8b1b9..2459529e9a2 100644 --- a/v3/internal/templates/_base/default/main.go.tmpl +++ b/v3/internal/templates/_base/default/main.go.tmpl @@ -16,7 +16,7 @@ func main() { Name: "{{.ProjectName}}", Description: "A demo of using raw HTML & CSS", Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/v3/internal/templates/_common/main.go.tmpl b/v3/internal/templates/_common/main.go.tmpl index b45568336eb..e4b1a628d4d 100644 --- a/v3/internal/templates/_common/main.go.tmpl +++ b/v3/internal/templates/_common/main.go.tmpl @@ -34,7 +34,7 @@ func main() { &GreetService{}, }, Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, From 57e6834bd2b69e59c4fdb0748c52c4a97729ca7a Mon Sep 17 00:00:00 2001 From: atterpac <89053530+atterpac@users.noreply.github.com> Date: Mon, 19 Feb 2024 11:49:17 -0800 Subject: [PATCH 035/369] NixOS font bug docs (#3268) add changelog Appeasing the rabbit remove v3 Co-authored-by: atterpac --- website/docs/guides/nixos-font.mdx | 10 ++++++++++ website/src/pages/changelog.mdx | 1 + 2 files changed, 11 insertions(+) create mode 100644 website/docs/guides/nixos-font.mdx diff --git a/website/docs/guides/nixos-font.mdx b/website/docs/guides/nixos-font.mdx new file mode 100644 index 00000000000..141e4d68caa --- /dev/null +++ b/website/docs/guides/nixos-font.mdx @@ -0,0 +1,10 @@ +# NixOS FontSize Bug + +NixOS/Wayland can cause a bug where the `font-size` css property doesnt affect the rendered page. To fix this add the following to your devShell. + +```shell + shellHook = with pkgs; '' + export XDG_DATA_DIRS=${gsettings-desktop-schemas}/share/gsettings-schemas/${gsettings-desktop-schemas.name}:${gtk3}/share/gsettings-schemas/${gtk3.name}:$XDG_DATA_DIRS; + export GIO_MODULE_DIR="${pkgs.glib-networking}/lib/gio/modules/"; + ''; +``` diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index b230d367a53..2739f263745 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Security` in case of vulnerabilities. ## [Unreleased] +- Added docs to help fix NixOs/Wayland font-size css issue. Added by @atterpac in [PR](https://github.com/wailsapp/wails/pull/3268) ## v2.8.0 - 2024-02-08 From 12d12a33dec1d31f487b70f87bc31e80252f327c Mon Sep 17 00:00:00 2001 From: stffabi Date: Wed, 21 Feb 2024 13:40:32 +0100 Subject: [PATCH 036/369] [v3, assetServer] Update docs --- mkdocs-website/docs/en/API/fullapi.md | 40 +++++++------------ mkdocs-website/docs/en/development/changes.md | 2 +- mkdocs-website/docs/en/whats-new.md | 4 +- mkdocs-website/docs/zh/development/changes.md | 2 +- mkdocs-website/docs/zh/whats-new.md | 4 +- 5 files changed, 21 insertions(+), 31 deletions(-) diff --git a/mkdocs-website/docs/en/API/fullapi.md b/mkdocs-website/docs/en/API/fullapi.md index 52ce0c2bffa..71d93d9a105 100644 --- a/mkdocs-website/docs/en/API/fullapi.md +++ b/mkdocs-website/docs/en/API/fullapi.md @@ -1205,31 +1205,21 @@ AssetOptions defines the configuration of the AssetServer. ```go type AssetOptions struct { - // FS defines the static assets to be used. A GET request is first tried to be served from this FS. If the FS returns - // `os.ErrNotExist` for that file, the request handling will fallback to the Handler and tries to serve the GET - // request from it. - // - // If set to nil, all GET requests will be forwarded to Handler. - FS fs.FS - - // Handler will be called for every GET request that can't be served from FS, due to `os.ErrNotExist`. Furthermore all - // non GET requests will always be served from this Handler. - // - // If not defined, the result is the following in cases where the Handler would have been called: - // GET request: `http.StatusNotFound` - // Other request: `http.StatusMethodNotAllowed` - Handler http.Handler - - // Middleware is HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default - // request handler dynamically, e.g. implement specialized Routing etc. - // The Middleware is called to build a new `http.Handler` used by the AssetSever and it also receives the default - // handler used by the AssetServer as an argument. - // - // If not defined, the default AssetServer request chain is executed. - // - // Multiple Middlewares can be chained together with: - // ChainMiddleware(middleware ...Middleware) Middleware - Middleware Middleware + // Handler which serves all the content to the WebView. + Handler http.Handler + + // Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default + // request handler dynamically, e.g. implement specialized Routing etc. + // The Middleware is called to build a new `http.Handler` used by the AssetSever and it also receives the default + // handler used by the AssetServer as an argument. + // + // This middleware injects itself before any of Wails internal middlewares. + // + // If not defined, the default AssetServer request chain is executed. + // + // Multiple Middlewares can be chained together with: + // ChainMiddleware(middleware ...Middleware) Middleware + Middleware Middleware // External URL can be set to a development server URL so that all requests are forwarded to it. This is useful // when using a development server like `vite` or `snowpack` which serves the assets on a different port. diff --git a/mkdocs-website/docs/en/development/changes.md b/mkdocs-website/docs/en/development/changes.md index 8a5377d635f..ba125147c91 100644 --- a/mkdocs-website/docs/en/development/changes.md +++ b/mkdocs-website/docs/en/development/changes.md @@ -164,7 +164,7 @@ Example: 2: 4021313248, }, Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/mkdocs-website/docs/en/whats-new.md b/mkdocs-website/docs/en/whats-new.md index a57c2a1e861..ac6ee16c458 100644 --- a/mkdocs-website/docs/en/whats-new.md +++ b/mkdocs-website/docs/en/whats-new.md @@ -25,7 +25,7 @@ func main() { app := application.New(application.Options{ Name: "Multi Window Demo", Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, }) @@ -243,7 +243,7 @@ func main() { Name: "Events Demo", Description: "A demo of the Events API", Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/mkdocs-website/docs/zh/development/changes.md b/mkdocs-website/docs/zh/development/changes.md index 7e44c6b3149..f830d67ef32 100644 --- a/mkdocs-website/docs/zh/development/changes.md +++ b/mkdocs-website/docs/zh/development/changes.md @@ -141,7 +141,7 @@ window.go.main = { 2: 4021313248, }, Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/mkdocs-website/docs/zh/whats-new.md b/mkdocs-website/docs/zh/whats-new.md index d76837e1074..9b175a35056 100644 --- a/mkdocs-website/docs/zh/whats-new.md +++ b/mkdocs-website/docs/zh/whats-new.md @@ -24,7 +24,7 @@ func main() { app := application.New(application.Options{ Name: "多窗口演示", Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, }) @@ -233,7 +233,7 @@ func main() { Name: "Events Demo", Description: "Events API演示", Assets: application.AssetOptions{ - FS: assets, + Handler: application.AssetFileServerFS(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, From 8145b0e0c573e553a80763127199aec300feb52e Mon Sep 17 00:00:00 2001 From: Benoit Botton Date: Thu, 22 Feb 2024 07:03:45 +0000 Subject: [PATCH 037/369] add warning about dynamic assets and vite v5.0.0+ (#3254) * add warning about dynamic assets and vite v5.0.0+ --- website/docs/guides/dynamic-assets.mdx | 9 +++++++++ website/docs/reference/options.mdx | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/website/docs/guides/dynamic-assets.mdx b/website/docs/guides/dynamic-assets.mdx index 0516fb72954..8d1debceff7 100644 --- a/website/docs/guides/dynamic-assets.mdx +++ b/website/docs/guides/dynamic-assets.mdx @@ -1,5 +1,14 @@ # Dynamic Assets +:::info + +This does not work with vite v5.0.0+ and wails v2 due to changes in vite. +Changes are planned in v3 to support similar functionality under vite v5.0.0+. +If you need this feature, stay with vite v4.0.0+. +See [issue 3240](https://github.com/wailsapp/wails/issues/3240) for details + +::: + If you want to load or generate assets for your frontend dynamically, you can achieve that using the [AssetsHandler](../reference/options#assetshandler) option. The AssetsHandler is a generic `http.Handler` which will be called for any non GET request on the assets server and for GET requests which can not be served from the diff --git a/website/docs/reference/options.mdx b/website/docs/reference/options.mdx index 26fb1afac27..19a599b3644 100644 --- a/website/docs/reference/options.mdx +++ b/website/docs/reference/options.mdx @@ -314,6 +314,15 @@ If not defined, the result is the following in cases where the Handler would hav - GET request: `http.StatusNotFound` - Other request: `http.StatusMethodNotAllowed` +:::info + +This does not work with vite v5.0.0+ and wails v2 due to changes in vite. +Changes are planned in v3 to support similar functionality under vite v5.0.0+. +If you need this feature, stay with vite v4.0.0+. +See [issue 3240](https://github.com/wailsapp/wails/issues/3240) for details + +::: + NOTE: When used in combination with a Frontend DevServer there might be limitations, eg. Vite serves the index.html on every path, that does not contain a file extension. From bff2258aea02258fd824983522c9b0d7a6ca7579 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Feb 2024 21:12:26 +1100 Subject: [PATCH 038/369] chore: update sponsors.svg (#3258) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 54 ++++++++++++++------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index 2e85cce46f4..1538fec3739 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -51,32 +51,28 @@ text { Julien Buying Breakfast - tc-hib - + tc-hib + - Tai Groot - - - - Michael - + Tai Groot + - Tom Wu - + Tom Wu + - Bironou - + Bironou + - Arden - + Arden + - igops - + igops + Buying Coffee @@ -125,50 +121,46 @@ text { Helpers - + - + - + - + - + - + - + - + - + - - - - - + - + From 65cef2f206ca043f4af6e6b8660dccb47ba3c2b3 Mon Sep 17 00:00:00 2001 From: te5se <133968742+te5se@users.noreply.github.com> Date: Mon, 26 Feb 2024 15:10:01 +0500 Subject: [PATCH 039/369] - add -m(skip go mod tidy) build flag to dev command (#3275) * - add -m(skip go mod tidy) build flag to dev command * - add changelog entry for PR #3275 --- v2/cmd/wails/flags/build.go | 1 - v2/cmd/wails/flags/buildcommon.go | 1 + v2/cmd/wails/internal/dev/dev.go | 10 ++++++---- website/src/pages/changelog.mdx | 1 + 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/v2/cmd/wails/flags/build.go b/v2/cmd/wails/flags/build.go index 974d9c3adc7..05b868ada72 100644 --- a/v2/cmd/wails/flags/build.go +++ b/v2/cmd/wails/flags/build.go @@ -25,7 +25,6 @@ type Build struct { BuildCommon NoPackage bool `name:"noPackage" description:"Skips platform specific packaging"` - SkipModTidy bool `name:"m" description:"Skip mod tidy before compile"` Upx bool `description:"Compress final binary with UPX (if installed)"` UpxFlags string `description:"Flags to pass to upx"` Platform string `description:"Platform to target. Comma separate multiple platforms"` diff --git a/v2/cmd/wails/flags/buildcommon.go b/v2/cmd/wails/flags/buildcommon.go index dcad33abffb..4bbc4c62ca5 100644 --- a/v2/cmd/wails/flags/buildcommon.go +++ b/v2/cmd/wails/flags/buildcommon.go @@ -9,6 +9,7 @@ type BuildCommon struct { Verbosity int `name:"v" description:"Verbosity level (0 = quiet, 1 = normal, 2 = verbose)"` Tags string `description:"Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated"` NoSyncGoMod bool `description:"Don't sync go.mod"` + SkipModTidy bool `name:"m" description:"Skip mod tidy before compile"` } func (c BuildCommon) Default() BuildCommon { diff --git a/v2/cmd/wails/internal/dev/dev.go b/v2/cmd/wails/internal/dev/dev.go index 02022d12132..2f6b10a7396 100644 --- a/v2/cmd/wails/internal/dev/dev.go +++ b/v2/cmd/wails/internal/dev/dev.go @@ -60,10 +60,12 @@ func Application(f *flags.Dev, logger *clilogger.CLILogger) error { return err } - // Run go mod tidy to ensure we're up-to-date - err = runCommand(cwd, false, f.Compiler, "mod", "tidy") - if err != nil { - return err + if !f.SkipModTidy { + // Run go mod tidy to ensure we're up-to-date + err = runCommand(cwd, false, f.Compiler, "mod", "tidy") + if err != nil { + return err + } } buildOptions := f.GenerateBuildOptions() diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index 2739f263745..62a6efe07ae 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Added docs to help fix NixOs/Wayland font-size css issue. Added by @atterpac in [PR](https://github.com/wailsapp/wails/pull/3268) +- Added -m (skip `go mod tidy`) flag to dev command by @te5se in [PR](https://github.com/wailsapp/wails/pull/3275) ## v2.8.0 - 2024-02-08 From b8537d1c96aa80bffa263893c10cb8756298afc8 Mon Sep 17 00:00:00 2001 From: Fabio Massaioli Date: Wed, 28 Feb 2024 22:42:57 +0100 Subject: [PATCH 040/369] [v3] Restore ToggleMaximise method in Window interface (#3281) * Add JS Window API example * Add ToggleMaximise button to Window API example * Restore ToggleMaximise method in Window interface * Update docs and changelog --- mkdocs-website/docs/en/API/fullapi.md | 11 + mkdocs-website/docs/en/changelog.md | 1 + v3/examples/window-api/README.md | 19 + v3/examples/window-api/assets/index.html | 155 +++ .../window-api/assets/runtime.debug.js | 963 ++++++++++++++++++ v3/examples/window-api/assets/runtime.js | 1 + v3/examples/window-api/main.go | 42 + .../build_assets/runtime/runtime.debug.js | 2 +- v3/internal/runtime/Taskfile.yaml | 3 +- v3/pkg/application/messageprocessor.go | 20 +- v3/pkg/application/messageprocessor_window.go | 3 + v3/pkg/application/webview_window.go | 14 + v3/pkg/application/window.go | 1 + v3/plugins/experimental/server/window.go | 2 + 14 files changed, 1225 insertions(+), 12 deletions(-) create mode 100644 v3/examples/window-api/README.md create mode 100644 v3/examples/window-api/assets/index.html create mode 100644 v3/examples/window-api/assets/runtime.debug.js create mode 100644 v3/examples/window-api/assets/runtime.js create mode 100644 v3/examples/window-api/main.go diff --git a/mkdocs-website/docs/en/API/fullapi.md b/mkdocs-website/docs/en/API/fullapi.md index 71d93d9a105..c6b505e9dd8 100644 --- a/mkdocs-website/docs/en/API/fullapi.md +++ b/mkdocs-website/docs/en/API/fullapi.md @@ -298,6 +298,7 @@ import "github.com/wailsapp/wails/v3/pkg/application" - [func \(w \*WebviewWindow\) Size\(\) \(int, int\)](#WebviewWindow.Size) - [func \(w \*WebviewWindow\) ToggleDevTools\(\)](#WebviewWindow.ToggleDevTools) - [func \(w \*WebviewWindow\) ToggleFullscreen\(\)](#WebviewWindow.ToggleFullscreen) + - [func \(w \*WebviewWindow\) ToggleMaximise\(\)](#WebviewWindow.ToggleMaximise) - [func \(w \*WebviewWindow\) UnFullscreen\(\)](#WebviewWindow.UnFullscreen) - [func \(w \*WebviewWindow\) UnMaximise\(\)](#WebviewWindow.UnMaximise) - [func \(w \*WebviewWindow\) UnMinimise\(\)](#WebviewWindow.UnMinimise) @@ -3715,6 +3716,16 @@ func (w *WebviewWindow) ToggleFullscreen() ToggleFullscreen toggles the window between fullscreen and normal + + +### func \(\*WebviewWindow\) [ToggleMaximise](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L720) + +```go +func (w *WebviewWindow) ToggleMaximise() +``` + +ToggleMaximise toggles the window between maximised and normal + ### func \(\*WebviewWindow\) [UnFullscreen](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L859) diff --git a/mkdocs-website/docs/en/changelog.md b/mkdocs-website/docs/en/changelog.md index 55854991712..8ea0a236c48 100644 --- a/mkdocs-website/docs/en/changelog.md +++ b/mkdocs-website/docs/en/changelog.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [linux] add task `run:linux` by [@marcus-crane](https://github.com/marcus-crane) in [#3146](https://github.com/wailsapp/wails/pull/3146) - export `SetIcon` method by @almas1992 in [PR](https://github.com/wailsapp/wails/pull/3147) - Improve `OnShutdown` by @almas1992 in [PR](https://github.com/wailsapp/wails/pull/3189) +- restore `ToggleMaximise` method in `Window` interface by [@fbbdev](https://github.com/fbbdev) in [#3281](https://github.com/wailsapp/wails/pull/3281) ### Fixed diff --git a/v3/examples/window-api/README.md b/v3/examples/window-api/README.md new file mode 100644 index 00000000000..02c72606263 --- /dev/null +++ b/v3/examples/window-api/README.md @@ -0,0 +1,19 @@ +# Window API Example + +This is an example of how to use the JS Window API + +## Running the example + +To run the example, simply run the following command: + +```bash +go run . +``` + +# Status + +| Platform | Status | +|----------|---------| +| Mac | Working | +| Windows | | +| Linux | | diff --git a/v3/examples/window-api/assets/index.html b/v3/examples/window-api/assets/index.html new file mode 100644 index 00000000000..29dc32d5be3 --- /dev/null +++ b/v3/examples/window-api/assets/index.html @@ -0,0 +1,155 @@ + + + + + Wails Alpha + + + + + +
Alpha
+
+

Close the Window?

+

Center

+

Minimise

+

Maximise

+

UnMaximise

+

Fullscreen

+

UnFullscreen

+

Restore

+
+
+

ToggleMaximise

+
+ + + + + diff --git a/v3/examples/window-api/assets/runtime.debug.js b/v3/examples/window-api/assets/runtime.debug.js new file mode 100644 index 00000000000..101f237755c --- /dev/null +++ b/v3/examples/window-api/assets/runtime.debug.js @@ -0,0 +1,963 @@ +(() => { + var __defProp = Object.defineProperty; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + + // desktop/@wailsio/runtime/src/log.js + function debugLog(message) { + console.log( + "%c wails3 %c " + message + " ", + "background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem", + "background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem" + ); + } + + // desktop/@wailsio/runtime/src/application.js + var application_exports = {}; + __export(application_exports, { + Hide: () => Hide, + Quit: () => Quit, + Show: () => Show + }); + + // node_modules/nanoid/non-secure/index.js + var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"; + var nanoid = (size2 = 21) => { + let id = ""; + let i = size2; + while (i--) { + id += urlAlphabet[Math.random() * 64 | 0]; + } + return id; + }; + + // desktop/@wailsio/runtime/src/runtime.js + var runtimeURL = window.location.origin + "/wails/runtime"; + var objectNames = { + Call: 0, + Clipboard: 1, + Application: 2, + Events: 3, + ContextMenu: 4, + Dialog: 5, + Window: 6, + Screens: 7, + System: 8, + Browser: 9 + }; + var clientId = nanoid(); + function newRuntimeCallerWithID(object, windowName) { + return function(method, args = null) { + return runtimeCallWithID(object, method, windowName, args); + }; + } + function runtimeCallWithID(objectID, method, windowName, args) { + let url = new URL(runtimeURL); + url.searchParams.append("object", objectID); + url.searchParams.append("method", method); + let fetchOptions = { + headers: {} + }; + if (windowName) { + fetchOptions.headers["x-wails-window-name"] = windowName; + } + if (args) { + url.searchParams.append("args", JSON.stringify(args)); + } + fetchOptions.headers["x-wails-client-id"] = clientId; + return new Promise((resolve, reject) => { + fetch(url, fetchOptions).then((response) => { + if (response.ok) { + if (response.headers.get("Content-Type") && response.headers.get("Content-Type").indexOf("application/json") !== -1) { + return response.json(); + } else { + return response.text(); + } + } + reject(Error(response.statusText)); + }).then((data) => resolve(data)).catch((error) => reject(error)); + }); + } + + // desktop/@wailsio/runtime/src/application.js + var call = newRuntimeCallerWithID(objectNames.Application, ""); + var HideMethod = 0; + var ShowMethod = 1; + var QuitMethod = 2; + function Hide() { + return call(HideMethod); + } + function Show() { + return call(ShowMethod); + } + function Quit() { + return call(QuitMethod); + } + + // desktop/@wailsio/runtime/src/browser.js + var browser_exports = {}; + __export(browser_exports, { + OpenURL: () => OpenURL + }); + var call2 = newRuntimeCallerWithID(objectNames.Browser, ""); + var BrowserOpenURL = 0; + function OpenURL(url) { + return call2(BrowserOpenURL, { url }); + } + + // desktop/@wailsio/runtime/src/clipboard.js + var clipboard_exports = {}; + __export(clipboard_exports, { + SetText: () => SetText, + Text: () => Text + }); + var call3 = newRuntimeCallerWithID(objectNames.Clipboard, ""); + var ClipboardSetText = 0; + var ClipboardText = 1; + function SetText(text) { + return call3(ClipboardSetText, { text }); + } + function Text() { + return call3(ClipboardText); + } + + // desktop/@wailsio/runtime/src/flags.js + var flags_exports = {}; + __export(flags_exports, { + GetFlag: () => GetFlag + }); + function GetFlag(keyString) { + try { + return window._wails.flags[keyString]; + } catch (e) { + throw new Error("Unable to retrieve flag '" + keyString + "': " + e); + } + } + + // desktop/@wailsio/runtime/src/screens.js + var screens_exports = {}; + __export(screens_exports, { + GetAll: () => GetAll, + GetCurrent: () => GetCurrent, + GetPrimary: () => GetPrimary + }); + var call4 = newRuntimeCallerWithID(objectNames.Screens, ""); + var getAll = 0; + var getPrimary = 1; + var getCurrent = 2; + function GetAll() { + return call4(getAll); + } + function GetPrimary() { + return call4(getPrimary); + } + function GetCurrent() { + return call4(getCurrent); + } + + // desktop/@wailsio/runtime/src/system.js + var system_exports = {}; + __export(system_exports, { + Capabilities: () => Capabilities, + Environment: () => Environment, + IsAMD64: () => IsAMD64, + IsARM: () => IsARM, + IsARM64: () => IsARM64, + IsDarkMode: () => IsDarkMode, + IsDebug: () => IsDebug, + IsLinux: () => IsLinux, + IsMac: () => IsMac, + IsWindows: () => IsWindows, + invoke: () => invoke + }); + var call5 = newRuntimeCallerWithID(objectNames.System, ""); + var systemIsDarkMode = 0; + var environment = 1; + function invoke(msg) { + if (window.chrome) { + return window.chrome.webview.postMessage(msg); + } + return window.webkit.messageHandlers.external.postMessage; + } + function IsDarkMode() { + return call5(systemIsDarkMode); + } + function Capabilities() { + let response = fetch("/wails/capabilities"); + return response.json(); + } + function Environment() { + return call5(environment); + } + function IsWindows() { + return window._wails.environment.OS === "windows"; + } + function IsLinux() { + return window._wails.environment.OS === "linux"; + } + function IsMac() { + return window._wails.environment.OS === "darwin"; + } + function IsAMD64() { + return window._wails.environment.Arch === "amd64"; + } + function IsARM() { + return window._wails.environment.Arch === "arm"; + } + function IsARM64() { + return window._wails.environment.Arch === "arm64"; + } + function IsDebug() { + return window._wails.environment.Debug === true; + } + + // desktop/@wailsio/runtime/src/window.js + var window_exports = {}; + __export(window_exports, { + Center: () => Center, + Close: () => Close, + Fullscreen: () => Fullscreen, + Get: () => Get, + GetZoomLevel: () => GetZoomLevel, + Height: () => Height, + Hide: () => Hide2, + Maximise: () => Maximise, + Minimise: () => Minimise, + RelativePosition: () => RelativePosition, + Restore: () => Restore, + Screen: () => Screen, + SetAlwaysOnTop: () => SetAlwaysOnTop, + SetBackgroundColour: () => SetBackgroundColour, + SetMaxSize: () => SetMaxSize, + SetMinSize: () => SetMinSize, + SetRelativePosition: () => SetRelativePosition, + SetResizable: () => SetResizable, + SetSize: () => SetSize, + SetTitle: () => SetTitle, + SetZoomLevel: () => SetZoomLevel, + Show: () => Show2, + Size: () => Size, + ToggleMaximise: () => ToggleMaximise, + UnMaximise: () => UnMaximise, + UnMinimise: () => UnMinimise, + Width: () => Width, + ZoomIn: () => ZoomIn, + ZoomOut: () => ZoomOut, + ZoomReset: () => ZoomReset + }); + var center = 0; + var setTitle = 1; + var fullscreen = 2; + var unFullscreen = 3; + var setSize = 4; + var size = 5; + var setMaxSize = 6; + var setMinSize = 7; + var setAlwaysOnTop = 8; + var setRelativePosition = 9; + var relativePosition = 10; + var screen = 11; + var hide = 12; + var maximise = 13; + var unMaximise = 14; + var toggleMaximise = 15; + var minimise = 16; + var unMinimise = 17; + var restore = 18; + var show = 19; + var close = 20; + var setBackgroundColour = 21; + var setResizable = 22; + var width = 23; + var height = 24; + var zoomIn = 25; + var zoomOut = 26; + var zoomReset = 27; + var getZoomLevel = 28; + var setZoomLevel = 29; + var thisWindow = Get(""); + function createWindow(call9) { + return { + Get: (windowName) => createWindow(newRuntimeCallerWithID(objectNames.Window, windowName)), + Center: () => call9(center), + SetTitle: (title) => call9(setTitle, { title }), + Fullscreen: () => call9(fullscreen), + UnFullscreen: () => call9(unFullscreen), + SetSize: (width2, height2) => call9(setSize, { width: width2, height: height2 }), + Size: () => call9(size), + SetMaxSize: (width2, height2) => call9(setMaxSize, { width: width2, height: height2 }), + SetMinSize: (width2, height2) => call9(setMinSize, { width: width2, height: height2 }), + SetAlwaysOnTop: (onTop) => call9(setAlwaysOnTop, { alwaysOnTop: onTop }), + SetRelativePosition: (x, y) => call9(setRelativePosition, { x, y }), + RelativePosition: () => call9(relativePosition), + Screen: () => call9(screen), + Hide: () => call9(hide), + Maximise: () => call9(maximise), + UnMaximise: () => call9(unMaximise), + ToggleMaximise: () => call9(toggleMaximise), + Minimise: () => call9(minimise), + UnMinimise: () => call9(unMinimise), + Restore: () => call9(restore), + Show: () => call9(show), + Close: () => call9(close), + SetBackgroundColour: (r, g, b, a) => call9(setBackgroundColour, { r, g, b, a }), + SetResizable: (resizable) => call9(setResizable, { resizable }), + Width: () => call9(width), + Height: () => call9(height), + ZoomIn: () => call9(zoomIn), + ZoomOut: () => call9(zoomOut), + ZoomReset: () => call9(zoomReset), + GetZoomLevel: () => call9(getZoomLevel), + SetZoomLevel: (zoomLevel) => call9(setZoomLevel, { zoomLevel }) + }; + } + function Get(windowName) { + return createWindow(newRuntimeCallerWithID(objectNames.Window, windowName)); + } + function Center() { + thisWindow.Center(); + } + function SetTitle(title) { + thisWindow.SetTitle(title); + } + function Fullscreen() { + thisWindow.Fullscreen(); + } + function SetSize(width2, height2) { + thisWindow.SetSize(width2, height2); + } + function Size() { + return thisWindow.Size(); + } + function SetMaxSize(width2, height2) { + thisWindow.SetMaxSize(width2, height2); + } + function SetMinSize(width2, height2) { + thisWindow.SetMinSize(width2, height2); + } + function SetAlwaysOnTop(onTop) { + thisWindow.SetAlwaysOnTop(onTop); + } + function SetRelativePosition(x, y) { + thisWindow.SetRelativePosition(x, y); + } + function RelativePosition() { + return thisWindow.RelativePosition(); + } + function Screen() { + return thisWindow.Screen(); + } + function Hide2() { + thisWindow.Hide(); + } + function Maximise() { + thisWindow.Maximise(); + } + function UnMaximise() { + thisWindow.UnMaximise(); + } + function ToggleMaximise() { + thisWindow.ToggleMaximise(); + } + function Minimise() { + thisWindow.Minimise(); + } + function UnMinimise() { + thisWindow.UnMinimise(); + } + function Restore() { + thisWindow.Restore(); + } + function Show2() { + thisWindow.Show(); + } + function Close() { + thisWindow.Close(); + } + function SetBackgroundColour(r, g, b, a) { + thisWindow.SetBackgroundColour(r, g, b, a); + } + function SetResizable(resizable) { + thisWindow.SetResizable(resizable); + } + function Width() { + return thisWindow.Width(); + } + function Height() { + return thisWindow.Height(); + } + function ZoomIn() { + thisWindow.ZoomIn(); + } + function ZoomOut() { + thisWindow.ZoomOut(); + } + function ZoomReset() { + thisWindow.ZoomReset(); + } + function GetZoomLevel() { + return thisWindow.GetZoomLevel(); + } + function SetZoomLevel(zoomLevel) { + thisWindow.SetZoomLevel(zoomLevel); + } + + // desktop/@wailsio/runtime/src/wml.js + var wml_exports = {}; + __export(wml_exports, { + Reload: () => Reload + }); + + // desktop/@wailsio/runtime/src/events.js + var events_exports = {}; + __export(events_exports, { + Emit: () => Emit, + Off: () => Off, + OffAll: () => OffAll, + On: () => On, + OnMultiple: () => OnMultiple, + Once: () => Once, + Types: () => Types, + WailsEvent: () => WailsEvent, + setup: () => setup + }); + + // desktop/@wailsio/runtime/src/event_types.js + var EventTypes = { + Windows: { + SystemThemeChanged: "windows:SystemThemeChanged", + APMPowerStatusChange: "windows:APMPowerStatusChange", + APMSuspend: "windows:APMSuspend", + APMResumeAutomatic: "windows:APMResumeAutomatic", + APMResumeSuspend: "windows:APMResumeSuspend", + APMPowerSettingChange: "windows:APMPowerSettingChange", + ApplicationStarted: "windows:ApplicationStarted", + WebViewNavigationCompleted: "windows:WebViewNavigationCompleted", + WindowInactive: "windows:WindowInactive", + WindowActive: "windows:WindowActive", + WindowClickActive: "windows:WindowClickActive", + WindowMaximise: "windows:WindowMaximise", + WindowUnMaximise: "windows:WindowUnMaximise", + WindowFullscreen: "windows:WindowFullscreen", + WindowUnFullscreen: "windows:WindowUnFullscreen", + WindowRestore: "windows:WindowRestore", + WindowMinimise: "windows:WindowMinimise", + WindowUnMinimise: "windows:WindowUnMinimise", + WindowClose: "windows:WindowClose", + WindowSetFocus: "windows:WindowSetFocus", + WindowKillFocus: "windows:WindowKillFocus", + WindowDragDrop: "windows:WindowDragDrop", + WindowDragEnter: "windows:WindowDragEnter", + WindowDragLeave: "windows:WindowDragLeave", + WindowDragOver: "windows:WindowDragOver" + }, + Mac: { + ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive", + ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties", + ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance", + ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon", + ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState", + ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters", + ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame", + ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation", + ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", + ApplicationDidHide: "mac:ApplicationDidHide", + ApplicationDidResignActiveNotification: "mac:ApplicationDidResignActiveNotification", + ApplicationDidUnhide: "mac:ApplicationDidUnhide", + ApplicationDidUpdate: "mac:ApplicationDidUpdate", + ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive", + ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching", + ApplicationWillHide: "mac:ApplicationWillHide", + ApplicationWillResignActive: "mac:ApplicationWillResignActive", + ApplicationWillTerminate: "mac:ApplicationWillTerminate", + ApplicationWillUnhide: "mac:ApplicationWillUnhide", + ApplicationWillUpdate: "mac:ApplicationWillUpdate", + ApplicationDidChangeTheme: "mac:ApplicationDidChangeTheme!", + ApplicationShouldHandleReopen: "mac:ApplicationShouldHandleReopen!", + WindowDidBecomeKey: "mac:WindowDidBecomeKey", + WindowDidBecomeMain: "mac:WindowDidBecomeMain", + WindowDidBeginSheet: "mac:WindowDidBeginSheet", + WindowDidChangeAlpha: "mac:WindowDidChangeAlpha", + WindowDidChangeBackingLocation: "mac:WindowDidChangeBackingLocation", + WindowDidChangeBackingProperties: "mac:WindowDidChangeBackingProperties", + WindowDidChangeCollectionBehavior: "mac:WindowDidChangeCollectionBehavior", + WindowDidChangeEffectiveAppearance: "mac:WindowDidChangeEffectiveAppearance", + WindowDidChangeOcclusionState: "mac:WindowDidChangeOcclusionState", + WindowDidChangeOrderingMode: "mac:WindowDidChangeOrderingMode", + WindowDidChangeScreen: "mac:WindowDidChangeScreen", + WindowDidChangeScreenParameters: "mac:WindowDidChangeScreenParameters", + WindowDidChangeScreenProfile: "mac:WindowDidChangeScreenProfile", + WindowDidChangeScreenSpace: "mac:WindowDidChangeScreenSpace", + WindowDidChangeScreenSpaceProperties: "mac:WindowDidChangeScreenSpaceProperties", + WindowDidChangeSharingType: "mac:WindowDidChangeSharingType", + WindowDidChangeSpace: "mac:WindowDidChangeSpace", + WindowDidChangeSpaceOrderingMode: "mac:WindowDidChangeSpaceOrderingMode", + WindowDidChangeTitle: "mac:WindowDidChangeTitle", + WindowDidChangeToolbar: "mac:WindowDidChangeToolbar", + WindowDidChangeVisibility: "mac:WindowDidChangeVisibility", + WindowDidDeminiaturize: "mac:WindowDidDeminiaturize", + WindowDidEndSheet: "mac:WindowDidEndSheet", + WindowDidEnterFullScreen: "mac:WindowDidEnterFullScreen", + WindowDidEnterVersionBrowser: "mac:WindowDidEnterVersionBrowser", + WindowDidExitFullScreen: "mac:WindowDidExitFullScreen", + WindowDidExitVersionBrowser: "mac:WindowDidExitVersionBrowser", + WindowDidExpose: "mac:WindowDidExpose", + WindowDidFocus: "mac:WindowDidFocus", + WindowDidMiniaturize: "mac:WindowDidMiniaturize", + WindowDidMove: "mac:WindowDidMove", + WindowDidOrderOffScreen: "mac:WindowDidOrderOffScreen", + WindowDidOrderOnScreen: "mac:WindowDidOrderOnScreen", + WindowDidResignKey: "mac:WindowDidResignKey", + WindowDidResignMain: "mac:WindowDidResignMain", + WindowDidResize: "mac:WindowDidResize", + WindowDidUpdate: "mac:WindowDidUpdate", + WindowDidUpdateAlpha: "mac:WindowDidUpdateAlpha", + WindowDidUpdateCollectionBehavior: "mac:WindowDidUpdateCollectionBehavior", + WindowDidUpdateCollectionProperties: "mac:WindowDidUpdateCollectionProperties", + WindowDidUpdateShadow: "mac:WindowDidUpdateShadow", + WindowDidUpdateTitle: "mac:WindowDidUpdateTitle", + WindowDidUpdateToolbar: "mac:WindowDidUpdateToolbar", + WindowDidUpdateVisibility: "mac:WindowDidUpdateVisibility", + WindowShouldClose: "mac:WindowShouldClose!", + WindowWillBecomeKey: "mac:WindowWillBecomeKey", + WindowWillBecomeMain: "mac:WindowWillBecomeMain", + WindowWillBeginSheet: "mac:WindowWillBeginSheet", + WindowWillChangeOrderingMode: "mac:WindowWillChangeOrderingMode", + WindowWillClose: "mac:WindowWillClose", + WindowWillDeminiaturize: "mac:WindowWillDeminiaturize", + WindowWillEnterFullScreen: "mac:WindowWillEnterFullScreen", + WindowWillEnterVersionBrowser: "mac:WindowWillEnterVersionBrowser", + WindowWillExitFullScreen: "mac:WindowWillExitFullScreen", + WindowWillExitVersionBrowser: "mac:WindowWillExitVersionBrowser", + WindowWillFocus: "mac:WindowWillFocus", + WindowWillMiniaturize: "mac:WindowWillMiniaturize", + WindowWillMove: "mac:WindowWillMove", + WindowWillOrderOffScreen: "mac:WindowWillOrderOffScreen", + WindowWillOrderOnScreen: "mac:WindowWillOrderOnScreen", + WindowWillResignMain: "mac:WindowWillResignMain", + WindowWillResize: "mac:WindowWillResize", + WindowWillUnfocus: "mac:WindowWillUnfocus", + WindowWillUpdate: "mac:WindowWillUpdate", + WindowWillUpdateAlpha: "mac:WindowWillUpdateAlpha", + WindowWillUpdateCollectionBehavior: "mac:WindowWillUpdateCollectionBehavior", + WindowWillUpdateCollectionProperties: "mac:WindowWillUpdateCollectionProperties", + WindowWillUpdateShadow: "mac:WindowWillUpdateShadow", + WindowWillUpdateTitle: "mac:WindowWillUpdateTitle", + WindowWillUpdateToolbar: "mac:WindowWillUpdateToolbar", + WindowWillUpdateVisibility: "mac:WindowWillUpdateVisibility", + WindowWillUseStandardFrame: "mac:WindowWillUseStandardFrame", + MenuWillOpen: "mac:MenuWillOpen", + MenuDidOpen: "mac:MenuDidOpen", + MenuDidClose: "mac:MenuDidClose", + MenuWillSendAction: "mac:MenuWillSendAction", + MenuDidSendAction: "mac:MenuDidSendAction", + MenuWillHighlightItem: "mac:MenuWillHighlightItem", + MenuDidHighlightItem: "mac:MenuDidHighlightItem", + MenuWillDisplayItem: "mac:MenuWillDisplayItem", + MenuDidDisplayItem: "mac:MenuDidDisplayItem", + MenuWillAddItem: "mac:MenuWillAddItem", + MenuDidAddItem: "mac:MenuDidAddItem", + MenuWillRemoveItem: "mac:MenuWillRemoveItem", + MenuDidRemoveItem: "mac:MenuDidRemoveItem", + MenuWillBeginTracking: "mac:MenuWillBeginTracking", + MenuDidBeginTracking: "mac:MenuDidBeginTracking", + MenuWillEndTracking: "mac:MenuWillEndTracking", + MenuDidEndTracking: "mac:MenuDidEndTracking", + MenuWillUpdate: "mac:MenuWillUpdate", + MenuDidUpdate: "mac:MenuDidUpdate", + MenuWillPopUp: "mac:MenuWillPopUp", + MenuDidPopUp: "mac:MenuDidPopUp", + MenuWillSendActionToItem: "mac:MenuWillSendActionToItem", + MenuDidSendActionToItem: "mac:MenuDidSendActionToItem", + WebViewDidStartProvisionalNavigation: "mac:WebViewDidStartProvisionalNavigation", + WebViewDidReceiveServerRedirectForProvisionalNavigation: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation", + WebViewDidFinishNavigation: "mac:WebViewDidFinishNavigation", + WebViewDidCommitNavigation: "mac:WebViewDidCommitNavigation", + WindowFileDraggingEntered: "mac:WindowFileDraggingEntered", + WindowFileDraggingPerformed: "mac:WindowFileDraggingPerformed", + WindowFileDraggingExited: "mac:WindowFileDraggingExited" + }, + Linux: { + SystemThemeChanged: "linux:SystemThemeChanged" + }, + Common: { + ApplicationStarted: "common:ApplicationStarted", + WindowMaximise: "common:WindowMaximise", + WindowUnMaximise: "common:WindowUnMaximise", + WindowFullscreen: "common:WindowFullscreen", + WindowUnFullscreen: "common:WindowUnFullscreen", + WindowRestore: "common:WindowRestore", + WindowMinimise: "common:WindowMinimise", + WindowUnMinimise: "common:WindowUnMinimise", + WindowClosing: "common:WindowClosing", + WindowZoom: "common:WindowZoom", + WindowZoomIn: "common:WindowZoomIn", + WindowZoomOut: "common:WindowZoomOut", + WindowZoomReset: "common:WindowZoomReset", + WindowFocus: "common:WindowFocus", + WindowLostFocus: "common:WindowLostFocus", + WindowShow: "common:WindowShow", + WindowHide: "common:WindowHide", + WindowDPIChanged: "common:WindowDPIChanged", + WindowFilesDropped: "common:WindowFilesDropped", + WindowRuntimeReady: "common:WindowRuntimeReady", + ThemeChanged: "common:ThemeChanged" + } + }; + + // desktop/@wailsio/runtime/src/events.js + var Types = EventTypes; + window._wails = window._wails || {}; + window._wails.dispatchWailsEvent = dispatchWailsEvent; + var call6 = newRuntimeCallerWithID(objectNames.Events, ""); + var EmitMethod = 0; + var eventListeners = /* @__PURE__ */ new Map(); + var Listener = class { + constructor(eventName, callback, maxCallbacks) { + this.eventName = eventName; + this.maxCallbacks = maxCallbacks || -1; + this.Callback = (data) => { + callback(data); + if (this.maxCallbacks === -1) + return false; + this.maxCallbacks -= 1; + return this.maxCallbacks === 0; + }; + } + }; + var WailsEvent = class { + constructor(name, data = null) { + this.name = name; + this.data = data; + } + }; + function setup() { + } + function dispatchWailsEvent(event) { + let listeners = eventListeners.get(event.name); + if (listeners) { + let toRemove = listeners.filter((listener) => { + let remove = listener.Callback(event); + if (remove) + return true; + }); + if (toRemove.length > 0) { + listeners = listeners.filter((l) => !toRemove.includes(l)); + if (listeners.length === 0) + eventListeners.delete(event.name); + else + eventListeners.set(event.name, listeners); + } + } + } + function OnMultiple(eventName, callback, maxCallbacks) { + let listeners = eventListeners.get(eventName) || []; + const thisListener = new Listener(eventName, callback, maxCallbacks); + listeners.push(thisListener); + eventListeners.set(eventName, listeners); + return () => listenerOff(thisListener); + } + function On(eventName, callback) { + return OnMultiple(eventName, callback, -1); + } + function Once(eventName, callback) { + return OnMultiple(eventName, callback, 1); + } + function listenerOff(listener) { + const eventName = listener.eventName; + let listeners = eventListeners.get(eventName).filter((l) => l !== listener); + if (listeners.length === 0) + eventListeners.delete(eventName); + else + eventListeners.set(eventName, listeners); + } + function Off(eventName, ...additionalEventNames) { + let eventsToRemove = [eventName, ...additionalEventNames]; + eventsToRemove.forEach((eventName2) => eventListeners.delete(eventName2)); + } + function OffAll() { + eventListeners.clear(); + } + function Emit(event) { + return call6(EmitMethod, event); + } + + // desktop/@wailsio/runtime/src/dialogs.js + var dialogs_exports = {}; + __export(dialogs_exports, { + Error: () => Error2, + Info: () => Info, + OpenFile: () => OpenFile, + Question: () => Question, + SaveFile: () => SaveFile, + Warning: () => Warning + }); + window._wails = window._wails || {}; + window._wails.dialogErrorCallback = dialogErrorCallback; + window._wails.dialogResultCallback = dialogResultCallback; + var DialogInfo = 0; + var DialogWarning = 1; + var DialogError = 2; + var DialogQuestion = 3; + var DialogOpenFile = 4; + var DialogSaveFile = 5; + var call7 = newRuntimeCallerWithID(objectNames.Dialog, ""); + var dialogResponses = /* @__PURE__ */ new Map(); + function generateID() { + let result; + do { + result = nanoid(); + } while (dialogResponses.has(result)); + return result; + } + function dialog(type, options = {}) { + const id = generateID(); + options["dialog-id"] = id; + return new Promise((resolve, reject) => { + dialogResponses.set(id, { resolve, reject }); + call7(type, options).catch((error) => { + reject(error); + dialogResponses.delete(id); + }); + }); + } + function dialogResultCallback(id, data, isJSON) { + let p = dialogResponses.get(id); + if (p) { + if (isJSON) { + p.resolve(JSON.parse(data)); + } else { + p.resolve(data); + } + dialogResponses.delete(id); + } + } + function dialogErrorCallback(id, message) { + let p = dialogResponses.get(id); + if (p) { + p.reject(message); + dialogResponses.delete(id); + } + } + var Info = (options) => dialog(DialogInfo, options); + var Warning = (options) => dialog(DialogWarning, options); + var Error2 = (options) => dialog(DialogError, options); + var Question = (options) => dialog(DialogQuestion, options); + var OpenFile = (options) => dialog(DialogOpenFile, options); + var SaveFile = (options) => dialog(DialogSaveFile, options); + + // desktop/@wailsio/runtime/src/wml.js + function sendEvent(eventName, data = null) { + let event = new WailsEvent(eventName, data); + Emit(event); + } + function addWMLEventListeners() { + const elements = document.querySelectorAll("[wml-event]"); + elements.forEach(function(element) { + const eventType = element.getAttribute("wml-event"); + const confirm = element.getAttribute("wml-confirm"); + const trigger = element.getAttribute("wml-trigger") || "click"; + let callback = function() { + if (confirm) { + Question({ Title: "Confirm", Message: confirm, Detached: false, Buttons: [{ Label: "Yes" }, { Label: "No", IsDefault: true }] }).then(function(result) { + if (result !== "No") { + sendEvent(eventType); + } + }); + return; + } + sendEvent(eventType); + }; + element.removeEventListener(trigger, callback); + element.addEventListener(trigger, callback); + }); + } + function callWindowMethod(windowName, method) { + let targetWindow = Get(windowName); + let methodMap = WindowMethods(targetWindow); + if (!methodMap.has(method)) { + console.log("Window method " + method + " not found"); + } + try { + methodMap.get(method)(); + } catch (e) { + console.error("Error calling window method '" + method + "': " + e); + } + } + function addWMLWindowListeners() { + const elements = document.querySelectorAll("[wml-window]"); + elements.forEach(function(element) { + const windowMethod = element.getAttribute("wml-window"); + const confirm = element.getAttribute("wml-confirm"); + const trigger = element.getAttribute("wml-trigger") || "click"; + const targetWindow = element.getAttribute("wml-target-window") || ""; + let callback = function() { + if (confirm) { + Question({ Title: "Confirm", Message: confirm, Buttons: [{ Label: "Yes" }, { Label: "No", IsDefault: true }] }).then(function(result) { + if (result !== "No") { + callWindowMethod(targetWindow, windowMethod); + } + }); + return; + } + callWindowMethod(targetWindow, windowMethod); + }; + element.removeEventListener(trigger, callback); + element.addEventListener(trigger, callback); + }); + } + function addWMLOpenBrowserListener() { + const elements = document.querySelectorAll("[wml-openurl]"); + elements.forEach(function(element) { + const url = element.getAttribute("wml-openurl"); + const confirm = element.getAttribute("wml-confirm"); + const trigger = element.getAttribute("wml-trigger") || "click"; + let callback = function() { + if (confirm) { + Question({ Title: "Confirm", Message: confirm, Buttons: [{ Label: "Yes" }, { Label: "No", IsDefault: true }] }).then(function(result) { + if (result !== "No") { + void OpenURL(url); + } + }); + return; + } + void OpenURL(url); + }; + element.removeEventListener(trigger, callback); + element.addEventListener(trigger, callback); + }); + } + function Reload() { + if (true) { + debugLog("Reloading WML"); + } + addWMLEventListeners(); + addWMLWindowListeners(); + addWMLOpenBrowserListener(); + } + function WindowMethods(targetWindow) { + let result = /* @__PURE__ */ new Map(); + for (let method in targetWindow) { + if (typeof targetWindow[method] === "function") { + result.set(method, targetWindow[method]); + } + } + return result; + } + + // desktop/@wailsio/runtime/src/calls.js + var calls_exports = {}; + __export(calls_exports, { + ByID: () => ByID, + ByName: () => ByName, + Call: () => Call, + Plugin: () => Plugin + }); + window._wails = window._wails || {}; + window._wails.callResultHandler = resultHandler; + window._wails.callErrorHandler = errorHandler; + var CallBinding = 0; + var call8 = newRuntimeCallerWithID(objectNames.Call, ""); + var callResponses = /* @__PURE__ */ new Map(); + function generateID2() { + let result; + do { + result = nanoid(); + } while (callResponses.has(result)); + return result; + } + function resultHandler(id, data, isJSON) { + const promiseHandler = getAndDeleteResponse(id); + if (promiseHandler) { + promiseHandler.resolve(isJSON ? JSON.parse(data) : data); + } + } + function errorHandler(id, message) { + const promiseHandler = getAndDeleteResponse(id); + if (promiseHandler) { + promiseHandler.reject(message); + } + } + function getAndDeleteResponse(id) { + const response = callResponses.get(id); + callResponses.delete(id); + return response; + } + function callBinding(type, options = {}) { + return new Promise((resolve, reject) => { + const id = generateID2(); + options["call-id"] = id; + callResponses.set(id, { resolve, reject }); + call8(type, options).catch((error) => { + reject(error); + callResponses.delete(id); + }); + }); + } + function Call(options) { + return callBinding(CallBinding, options); + } + function ByName(name, ...args) { + if (typeof name !== "string" || name.split(".").length !== 3) { + throw new Error("CallByName requires a string in the format 'package.struct.method'"); + } + let [packageName, structName, methodName] = name.split("."); + return callBinding(CallBinding, { + packageName, + structName, + methodName, + args + }); + } + function ByID(methodID, ...args) { + return callBinding(CallBinding, { + methodID, + args + }); + } + function Plugin(pluginName, methodName, ...args) { + return callBinding(CallBinding, { + packageName: "wails-plugins", + structName: pluginName, + methodName, + args + }); + } + + // desktop/compiled/main.js + window._wails = window._wails || {}; + window._wails.invoke = invoke; + window.wails = window.wails || {}; + window.wails.Application = application_exports; + window.wails.Browser = browser_exports; + window.wails.Call = calls_exports; + window.wails.Clipboard = clipboard_exports; + window.wails.Dialogs = dialogs_exports; + window.wails.Events = events_exports; + window.wails.Flags = flags_exports; + window.wails.Screens = screens_exports; + window.wails.System = system_exports; + window.wails.Window = window_exports; + window.wails.WML = wml_exports; + var isReady = false; + document.addEventListener("DOMContentLoaded", function() { + isReady = true; + window._wails.invoke("wails:runtime:ready"); + if (true) { + debugLog("Wails Runtime Loaded"); + } + }); + function whenReady(fn) { + if (isReady || document.readyState === "complete") { + fn(); + } else { + document.addEventListener("DOMContentLoaded", fn); + } + } + whenReady(() => { + Reload(); + }); +})(); +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb24uanMiLCAiLi4vLi4vLi4vcnVudGltZS9ub2RlX21vZHVsZXMvbmFub2lkL25vbi1zZWN1cmUvaW5kZXguanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3J1bnRpbWUuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXIuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZC5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3MuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3NjcmVlbnMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbS5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvd2luZG93LmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy93bWwuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50cy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZXZlbnRfdHlwZXMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RpYWxvZ3MuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NhbGxzLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9jb21waWxlZC9tYWluLmpzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcclxuICogTG9ncyBhIG1lc3NhZ2UgdG8gdGhlIGNvbnNvbGUgd2l0aCBjdXN0b20gZm9ybWF0dGluZy5cclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQuXHJcbiAqIEByZXR1cm4ge3ZvaWR9XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZGVidWdMb2cobWVzc2FnZSkge1xyXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXHJcbiAgICBjb25zb2xlLmxvZyhcclxuICAgICAgICAnJWMgd2FpbHMzICVjICcgKyBtZXNzYWdlICsgJyAnLFxyXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjYWEwMDAwOyBjb2xvcjogI2ZmZjsgYm9yZGVyLXJhZGl1czogM3B4IDBweCAwcHggM3B4OyBwYWRkaW5nOiAxcHg7IGZvbnQtc2l6ZTogMC43cmVtJyxcclxuICAgICAgICAnYmFja2dyb3VuZDogIzAwOTkwMDsgY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDBweCAzcHggM3B4IDBweDsgcGFkZGluZzogMXB4OyBmb250LXNpemU6IDAuN3JlbSdcclxuICAgICk7XHJcbn0iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5cclxuaW1wb3J0IHsgbmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXMgfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkFwcGxpY2F0aW9uLCAnJyk7XHJcblxyXG5jb25zdCBIaWRlTWV0aG9kID0gMDtcclxuY29uc3QgU2hvd01ldGhvZCA9IDE7XHJcbmNvbnN0IFF1aXRNZXRob2QgPSAyO1xyXG5cclxuLyoqXHJcbiAqIEhpZGVzIGEgY2VydGFpbiBtZXRob2QgYnkgY2FsbGluZyB0aGUgSGlkZU1ldGhvZCBmdW5jdGlvbi5cclxuICpcclxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cclxuICpcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBIaWRlKCkge1xyXG4gICAgcmV0dXJuIGNhbGwoSGlkZU1ldGhvZCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDYWxscyB0aGUgU2hvd01ldGhvZCBhbmQgcmV0dXJucyB0aGUgcmVzdWx0LlxyXG4gKlxyXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNob3coKSB7XHJcbiAgICByZXR1cm4gY2FsbChTaG93TWV0aG9kKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENhbGxzIHRoZSBRdWl0TWV0aG9kIHRvIHRlcm1pbmF0ZSB0aGUgcHJvZ3JhbS5cclxuICpcclxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBRdWl0KCkge1xyXG4gICAgcmV0dXJuIGNhbGwoUXVpdE1ldGhvZCk7XHJcbn1cclxuIiwgImxldCB1cmxBbHBoYWJldCA9XG4gICd1c2VhbmRvbS0yNlQxOTgzNDBQWDc1cHhKQUNLVkVSWU1JTkRCVVNIV09MRl9HUVpiZmdoamtscXZ3eXpyaWN0J1xuZXhwb3J0IGxldCBjdXN0b21BbHBoYWJldCA9IChhbHBoYWJldCwgZGVmYXVsdFNpemUgPSAyMSkgPT4ge1xuICByZXR1cm4gKHNpemUgPSBkZWZhdWx0U2l6ZSkgPT4ge1xuICAgIGxldCBpZCA9ICcnXG4gICAgbGV0IGkgPSBzaXplXG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgaWQgKz0gYWxwaGFiZXRbKE1hdGgucmFuZG9tKCkgKiBhbHBoYWJldC5sZW5ndGgpIHwgMF1cbiAgICB9XG4gICAgcmV0dXJuIGlkXG4gIH1cbn1cbmV4cG9ydCBsZXQgbmFub2lkID0gKHNpemUgPSAyMSkgPT4ge1xuICBsZXQgaWQgPSAnJ1xuICBsZXQgaSA9IHNpemVcbiAgd2hpbGUgKGktLSkge1xuICAgIGlkICs9IHVybEFscGhhYmV0WyhNYXRoLnJhbmRvbSgpICogNjQpIHwgMF1cbiAgfVxuICByZXR1cm4gaWRcbn1cbiIsICIvKlxyXG4gXyAgICAgX18gICAgIF8gX19cclxufCB8ICAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXHJcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZC9ub24tc2VjdXJlJztcclxuXHJcbmNvbnN0IHJ1bnRpbWVVUkwgPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luICsgXCIvd2FpbHMvcnVudGltZVwiO1xyXG5cclxuLy8gT2JqZWN0IE5hbWVzXHJcbmV4cG9ydCBjb25zdCBvYmplY3ROYW1lcyA9IHtcclxuICAgIENhbGw6IDAsXHJcbiAgICBDbGlwYm9hcmQ6IDEsXHJcbiAgICBBcHBsaWNhdGlvbjogMixcclxuICAgIEV2ZW50czogMyxcclxuICAgIENvbnRleHRNZW51OiA0LFxyXG4gICAgRGlhbG9nOiA1LFxyXG4gICAgV2luZG93OiA2LFxyXG4gICAgU2NyZWVuczogNyxcclxuICAgIFN5c3RlbTogOCxcclxuICAgIEJyb3dzZXI6IDksXHJcbn1cclxuZXhwb3J0IGxldCBjbGllbnRJZCA9IG5hbm9pZCgpO1xyXG5cclxuLyoqXHJcbiAqIENyZWF0ZXMgYSBydW50aW1lIGNhbGxlciBmdW5jdGlvbiB0aGF0IGludm9rZXMgYSBzcGVjaWZpZWQgbWV0aG9kIG9uIGEgZ2l2ZW4gb2JqZWN0IHdpdGhpbiBhIHNwZWNpZmllZCB3aW5kb3cgY29udGV4dC5cclxuICpcclxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3Qgb24gd2hpY2ggdGhlIG1ldGhvZCBpcyB0byBiZSBpbnZva2VkLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgY29udGV4dCBpbiB3aGljaCB0aGUgbWV0aG9kIHNob3VsZCBiZSBjYWxsZWQuXHJcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gQSBydW50aW1lIGNhbGxlciBmdW5jdGlvbiB0aGF0IHRha2VzIHRoZSBtZXRob2QgbmFtZSBhbmQgb3B0aW9uYWxseSBhcmd1bWVudHMgYW5kIGludm9rZXMgdGhlIG1ldGhvZCB3aXRoaW4gdGhlIHNwZWNpZmllZCB3aW5kb3cgY29udGV4dC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdCwgd2luZG93TmFtZSkge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uIChtZXRob2QsIGFyZ3M9bnVsbCkge1xyXG4gICAgICAgIHJldHVybiBydW50aW1lQ2FsbChvYmplY3QgKyBcIi5cIiArIG1ldGhvZCwgd2luZG93TmFtZSwgYXJncyk7XHJcbiAgICB9O1xyXG59XHJcblxyXG4vKipcclxuICogQ3JlYXRlcyBhIG5ldyBydW50aW1lIGNhbGxlciB3aXRoIHNwZWNpZmllZCBJRC5cclxuICpcclxuICogQHBhcmFtIHtvYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3QgdG8gaW52b2tlIHRoZSBtZXRob2Qgb24uXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSB3aW5kb3dOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHdpbmRvdy5cclxuICogQHJldHVybiB7RnVuY3Rpb259IC0gVGhlIG5ldyBydW50aW1lIGNhbGxlciBmdW5jdGlvbi5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdCwgd2luZG93TmFtZSkge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uIChtZXRob2QsIGFyZ3M9bnVsbCkge1xyXG4gICAgICAgIHJldHVybiBydW50aW1lQ2FsbFdpdGhJRChvYmplY3QsIG1ldGhvZCwgd2luZG93TmFtZSwgYXJncyk7XHJcbiAgICB9O1xyXG59XHJcblxyXG5cclxuZnVuY3Rpb24gcnVudGltZUNhbGwobWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKSB7XHJcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcclxuICAgIGlmKCBtZXRob2QgKSB7XHJcbiAgICAgICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJtZXRob2RcIiwgbWV0aG9kKTtcclxuICAgIH1cclxuICAgIGxldCBmZXRjaE9wdGlvbnMgPSB7XHJcbiAgICAgICAgaGVhZGVyczoge30sXHJcbiAgICB9O1xyXG4gICAgaWYgKHdpbmRvd05hbWUpIHtcclxuICAgICAgICBmZXRjaE9wdGlvbnMuaGVhZGVyc1tcIngtd2FpbHMtd2luZG93LW5hbWVcIl0gPSB3aW5kb3dOYW1lO1xyXG4gICAgfVxyXG4gICAgaWYgKGFyZ3MpIHtcclxuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcImFyZ3NcIiwgSlNPTi5zdHJpbmdpZnkoYXJncykpO1xyXG4gICAgfVxyXG4gICAgZmV0Y2hPcHRpb25zLmhlYWRlcnNbXCJ4LXdhaWxzLWNsaWVudC1pZFwiXSA9IGNsaWVudElkO1xyXG5cclxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgZmV0Y2godXJsLCBmZXRjaE9wdGlvbnMpXHJcbiAgICAgICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcclxuICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5vaykge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGNvbnRlbnQgdHlwZVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKSAmJiByZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKS5pbmRleE9mKFwiYXBwbGljYXRpb24vanNvblwiKSAhPT0gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcihyZXNwb25zZS5zdGF0dXNUZXh0KSk7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIC50aGVuKGRhdGEgPT4gcmVzb2x2ZShkYXRhKSlcclxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHJ1bnRpbWVDYWxsV2l0aElEKG9iamVjdElELCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcclxuICAgIGxldCB1cmwgPSBuZXcgVVJMKHJ1bnRpbWVVUkwpO1xyXG4gICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJvYmplY3RcIiwgb2JqZWN0SUQpO1xyXG4gICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJtZXRob2RcIiwgbWV0aG9kKTtcclxuICAgIGxldCBmZXRjaE9wdGlvbnMgPSB7XHJcbiAgICAgICAgaGVhZGVyczoge30sXHJcbiAgICB9O1xyXG4gICAgaWYgKHdpbmRvd05hbWUpIHtcclxuICAgICAgICBmZXRjaE9wdGlvbnMuaGVhZGVyc1tcIngtd2FpbHMtd2luZG93LW5hbWVcIl0gPSB3aW5kb3dOYW1lO1xyXG4gICAgfVxyXG4gICAgaWYgKGFyZ3MpIHtcclxuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcImFyZ3NcIiwgSlNPTi5zdHJpbmdpZnkoYXJncykpO1xyXG4gICAgfVxyXG4gICAgZmV0Y2hPcHRpb25zLmhlYWRlcnNbXCJ4LXdhaWxzLWNsaWVudC1pZFwiXSA9IGNsaWVudElkO1xyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgICBmZXRjaCh1cmwsIGZldGNoT3B0aW9ucylcclxuICAgICAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLm9rKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgY29udGVudCB0eXBlXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpICYmIHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpLmluZGV4T2YoXCJhcHBsaWNhdGlvbi9qc29uXCIpICE9PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKHJlc3BvbnNlLnN0YXR1c1RleHQpKTtcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgLnRoZW4oZGF0YSA9PiByZXNvbHZlKGRhdGEpKVxyXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XHJcbiAgICB9KTtcclxufVxyXG4iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcblxyXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5Ccm93c2VyLCAnJyk7XHJcbmNvbnN0IEJyb3dzZXJPcGVuVVJMID0gMDtcclxuXHJcbi8qKlxyXG4gKiBPcGVuIGEgYnJvd3NlciB3aW5kb3cgdG8gdGhlIGdpdmVuIFVSTFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIC0gVGhlIFVSTCB0byBvcGVuXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gT3BlblVSTCh1cmwpIHtcclxuICAgIHJldHVybiBjYWxsKEJyb3dzZXJPcGVuVVJMLCB7dXJsfSk7XHJcbn1cclxuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcclxuXHJcbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkNsaXBib2FyZCwgJycpO1xyXG5jb25zdCBDbGlwYm9hcmRTZXRUZXh0ID0gMDtcclxuY29uc3QgQ2xpcGJvYXJkVGV4dCA9IDE7XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgdGV4dCB0byB0aGUgQ2xpcGJvYXJkLlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gdGV4dCAtIFRoZSB0ZXh0IHRvIGJlIHNldCB0byB0aGUgQ2xpcGJvYXJkLlxyXG4gKiBAcmV0dXJuIHtQcm9taXNlfSAtIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIG9wZXJhdGlvbiBpcyBzdWNjZXNzZnVsLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldFRleHQodGV4dCkge1xyXG4gICAgcmV0dXJuIGNhbGwoQ2xpcGJvYXJkU2V0VGV4dCwge3RleHR9KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldCB0aGUgQ2xpcGJvYXJkIHRleHRcclxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgdGV4dCBmcm9tIHRoZSBDbGlwYm9hcmQuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gVGV4dCgpIHtcclxuICAgIHJldHVybiBjYWxsKENsaXBib2FyZFRleHQpO1xyXG59XHJcbiIsICIvKlxyXG4gX1x0ICAgX19cdCAgXyBfX1xyXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXHJcblxyXG4vKipcclxuICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBrZXkgZnJvbSB0aGUgZmxhZyBtYXAuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXlTdHJpbmcgLSBUaGUga2V5IHRvIHJldHJpZXZlIHRoZSB2YWx1ZSBmb3IuXHJcbiAqIEByZXR1cm4geyp9IC0gVGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgc3BlY2lmaWVkIGtleS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBHZXRGbGFnKGtleVN0cmluZykge1xyXG4gICAgdHJ5IHtcclxuICAgICAgICByZXR1cm4gd2luZG93Ll93YWlscy5mbGFnc1trZXlTdHJpbmddO1xyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byByZXRyaWV2ZSBmbGFnICdcIiArIGtleVN0cmluZyArIFwiJzogXCIgKyBlKTtcclxuICAgIH1cclxufVxyXG4iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFBvc2l0aW9uXHJcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIFggY29vcmRpbmF0ZS5cclxuICogQHByb3BlcnR5IHtudW1iZXJ9IFkgLSBUaGUgWSBjb29yZGluYXRlLlxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBTaXplXHJcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIHdpZHRoLlxyXG4gKiBAcHJvcGVydHkge251bWJlcn0gWSAtIFRoZSBoZWlnaHQuXHJcbiAqL1xyXG5cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBSZWN0XHJcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIFggY29vcmRpbmF0ZSBvZiB0aGUgdG9wLWxlZnQgY29ybmVyLlxyXG4gKiBAcHJvcGVydHkge251bWJlcn0gWSAtIFRoZSBZIGNvb3JkaW5hdGUgb2YgdGhlIHRvcC1sZWZ0IGNvcm5lci5cclxuICogQHByb3BlcnR5IHtudW1iZXJ9IFdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSByZWN0YW5nbGUuXHJcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBIZWlnaHQgLSBUaGUgaGVpZ2h0IG9mIHRoZSByZWN0YW5nbGUuXHJcbiAqL1xyXG5cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7KCdaZXJvJ3wnTmluZXR5J3wnT25lRWlnaHR5J3wnVHdvU2V2ZW50eScpfSBSb3RhdGlvblxyXG4gKiBUaGUgcm90YXRpb24gb2YgdGhlIHNjcmVlbi4gQ2FuIGJlIG9uZSBvZiAnWmVybycsICdOaW5ldHknLCAnT25lRWlnaHR5JywgJ1R3b1NldmVudHknLlxyXG4gKi9cclxuXHJcblxyXG4vKipcclxuICogQHR5cGVkZWYge09iamVjdH0gU2NyZWVuXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBJZCAtIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgc2NyZWVuLlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTmFtZSAtIEh1bWFuIHJlYWRhYmxlIG5hbWUgb2YgdGhlIHNjcmVlbi5cclxuICogQHByb3BlcnR5IHtudW1iZXJ9IFNjYWxlIC0gVGhlIHJlc29sdXRpb24gc2NhbGUgb2YgdGhlIHNjcmVlbi4gMSA9IHN0YW5kYXJkIHJlc29sdXRpb24sIDIgPSBoaWdoIChSZXRpbmEpLCBldGMuXHJcbiAqIEBwcm9wZXJ0eSB7UG9zaXRpb259IFBvc2l0aW9uIC0gQ29udGFpbnMgdGhlIFggYW5kIFkgY29vcmRpbmF0ZXMgb2YgdGhlIHNjcmVlbidzIHBvc2l0aW9uLlxyXG4gKiBAcHJvcGVydHkge1NpemV9IFNpemUgLSBDb250YWlucyB0aGUgd2lkdGggYW5kIGhlaWdodCBvZiB0aGUgc2NyZWVuLlxyXG4gKiBAcHJvcGVydHkge1JlY3R9IEJvdW5kcyAtIENvbnRhaW5zIHRoZSBib3VuZHMgb2YgdGhlIHNjcmVlbiBpbiB0ZXJtcyBvZiBYLCBZLCBXaWR0aCwgYW5kIEhlaWdodC5cclxuICogQHByb3BlcnR5IHtSZWN0fSBXb3JrQXJlYSAtIENvbnRhaW5zIHRoZSBhcmVhIG9mIHRoZSBzY3JlZW4gdGhhdCBpcyBhY3R1YWxseSB1c2FibGUgKGV4Y2x1ZGluZyB0YXNrYmFyIGFuZCBvdGhlciBzeXN0ZW0gVUkpLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IElzUHJpbWFyeSAtIFRydWUgaWYgdGhpcyBpcyB0aGUgcHJpbWFyeSBtb25pdG9yIHNlbGVjdGVkIGJ5IHRoZSB1c2VyIGluIHRoZSBvcGVyYXRpbmcgc3lzdGVtLlxyXG4gKiBAcHJvcGVydHkge1JvdGF0aW9ufSBSb3RhdGlvbiAtIFRoZSByb3RhdGlvbiBvZiB0aGUgc2NyZWVuLlxyXG4gKi9cclxuXHJcblxyXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLlNjcmVlbnMsICcnKTtcclxuXHJcbmNvbnN0IGdldEFsbCA9IDA7XHJcbmNvbnN0IGdldFByaW1hcnkgPSAxO1xyXG5jb25zdCBnZXRDdXJyZW50ID0gMjtcclxuXHJcbi8qKlxyXG4gKiBHZXRzIGFsbCBzY3JlZW5zLlxyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxTY3JlZW5bXT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IG9mIFNjcmVlbiBvYmplY3RzLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEdldEFsbCgpIHtcclxuICAgIHJldHVybiBjYWxsKGdldEFsbCk7XHJcbn1cclxuLyoqXHJcbiAqIEdldHMgdGhlIHByaW1hcnkgc2NyZWVuLlxyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxTY3JlZW4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgcHJpbWFyeSBzY3JlZW4uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gR2V0UHJpbWFyeSgpIHtcclxuICAgIHJldHVybiBjYWxsKGdldFByaW1hcnkpO1xyXG59XHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBjdXJyZW50IGFjdGl2ZSBzY3JlZW4uXHJcbiAqXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPFNjcmVlbj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGN1cnJlbnQgYWN0aXZlIHNjcmVlbi5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBHZXRDdXJyZW50KCkge1xyXG4gICAgcmV0dXJuIGNhbGwoZ2V0Q3VycmVudCk7XHJcbn0iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5cclxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xyXG5sZXQgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU3lzdGVtLCAnJyk7XHJcbmNvbnN0IHN5c3RlbUlzRGFya01vZGUgPSAwO1xyXG5jb25zdCBlbnZpcm9ubWVudCA9IDE7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gaW52b2tlKG1zZykge1xyXG4gICAgaWYod2luZG93LmNocm9tZSkge1xyXG4gICAgICAgIHJldHVybiB3aW5kb3cuY2hyb21lLndlYnZpZXcucG9zdE1lc3NhZ2UobXNnKTtcclxuICAgIH1cclxuICAgIHJldHVybiB3aW5kb3cud2Via2l0Lm1lc3NhZ2VIYW5kbGVycy5leHRlcm5hbC5wb3N0TWVzc2FnZTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBSZXRyaWV2ZXMgdGhlIHN5c3RlbSBkYXJrIG1vZGUgc3RhdHVzLlxyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxib29sZWFuPn0gLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIGJvb2xlYW4gdmFsdWUgaW5kaWNhdGluZyBpZiB0aGUgc3lzdGVtIGlzIGluIGRhcmsgbW9kZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBJc0RhcmtNb2RlKCkge1xyXG4gICAgcmV0dXJuIGNhbGwoc3lzdGVtSXNEYXJrTW9kZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBGZXRjaGVzIHRoZSBjYXBhYmlsaXRpZXMgb2YgdGhlIGFwcGxpY2F0aW9uIGZyb20gdGhlIHNlcnZlci5cclxuICpcclxuICogQGFzeW5jXHJcbiAqIEBmdW5jdGlvbiBDYXBhYmlsaXRpZXNcclxuICogQHJldHVybnMge1Byb21pc2U8T2JqZWN0Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGNhcGFiaWxpdGllcy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBDYXBhYmlsaXRpZXMoKSB7XHJcbiAgICBsZXQgcmVzcG9uc2UgPSBmZXRjaChcIi93YWlscy9jYXBhYmlsaXRpZXNcIik7XHJcbiAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xyXG59XHJcblxyXG4vKipcclxuICogQHR5cGVkZWYge29iamVjdH0gRW52aXJvbm1lbnRJbmZvXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBPUyAtIFRoZSBvcGVyYXRpbmcgc3lzdGVtIGluIHVzZS5cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IEFyY2ggLSBUaGUgYXJjaGl0ZWN0dXJlIG9mIHRoZSBzeXN0ZW0uXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBSZXRyaWV2ZXMgZW52aXJvbm1lbnQgZGV0YWlscy5cclxuICogQHJldHVybnMge1Byb21pc2U8RW52aXJvbm1lbnRJbmZvPn0gLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBvYmplY3QgY29udGFpbmluZyBPUyBhbmQgc3lzdGVtIGFyY2hpdGVjdHVyZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFbnZpcm9ubWVudCgpIHtcclxuICAgIHJldHVybiBjYWxsKGVudmlyb25tZW50KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIFdpbmRvd3MuXHJcbiAqXHJcbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgdGhlIG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cywgb3RoZXJ3aXNlIGZhbHNlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIElzV2luZG93cygpIHtcclxuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcIndpbmRvd3NcIjtcclxufVxyXG5cclxuLyoqXHJcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIExpbnV4LlxyXG4gKlxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgTGludXgsIGZhbHNlIG90aGVyd2lzZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBJc0xpbnV4KCkge1xyXG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuT1MgPT09IFwibGludXhcIjtcclxufVxyXG5cclxuLyoqXHJcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBpcyBhIG1hY09TIG9wZXJhdGluZyBzeXN0ZW0uXHJcbiAqXHJcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBlbnZpcm9ubWVudCBpcyBtYWNPUywgZmFsc2Ugb3RoZXJ3aXNlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIElzTWFjKCkge1xyXG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuT1MgPT09IFwiZGFyd2luXCI7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgYXJjaGl0ZWN0dXJlIGlzIEFNRDY0LlxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQsIGZhbHNlIG90aGVyd2lzZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBJc0FNRDY0KCkge1xyXG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuQXJjaCA9PT0gXCJhbWQ2NFwiO1xyXG59XHJcblxyXG4vKipcclxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGFyY2hpdGVjdHVyZSBpcyBBUk0uXHJcbiAqXHJcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBjdXJyZW50IGFyY2hpdGVjdHVyZSBpcyBBUk0sIGZhbHNlIG90aGVyd2lzZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBJc0FSTSgpIHtcclxuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtXCI7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgaXMgQVJNNjQgYXJjaGl0ZWN0dXJlLlxyXG4gKlxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBSZXR1cm5zIHRydWUgaWYgdGhlIGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZSwgb3RoZXJ3aXNlIHJldHVybnMgZmFsc2UuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gSXNBUk02NCgpIHtcclxuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtNjRcIjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIElzRGVidWcoKSB7XHJcbiAgICByZXR1cm4gd2luZG93Ll93YWlscy5lbnZpcm9ubWVudC5EZWJ1ZyA9PT0gdHJ1ZTtcclxufVxyXG5cclxuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbi8vIEltcG9ydCBzY3JlZW4ganNkb2MgZGVmaW5pdGlvbiBmcm9tIC4vc2NyZWVucy5qc1xyXG4vKipcclxuICogQHR5cGVkZWYge2ltcG9ydChcIi4vc2NyZWVuc1wiKS5TY3JlZW59IFNjcmVlblxyXG4gKi9cclxuXHJcbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcclxuXHJcbmNvbnN0IGNlbnRlciA9IDA7XHJcbmNvbnN0IHNldFRpdGxlID0gMTtcclxuY29uc3QgZnVsbHNjcmVlbiA9IDI7XHJcbmNvbnN0IHVuRnVsbHNjcmVlbiA9IDM7XHJcbmNvbnN0IHNldFNpemUgPSA0O1xyXG5jb25zdCBzaXplID0gNTtcclxuY29uc3Qgc2V0TWF4U2l6ZSA9IDY7XHJcbmNvbnN0IHNldE1pblNpemUgPSA3O1xyXG5jb25zdCBzZXRBbHdheXNPblRvcCA9IDg7XHJcbmNvbnN0IHNldFJlbGF0aXZlUG9zaXRpb24gPSA5O1xyXG5jb25zdCByZWxhdGl2ZVBvc2l0aW9uID0gMTA7XHJcbmNvbnN0IHNjcmVlbiA9IDExO1xyXG5jb25zdCBoaWRlID0gMTI7XHJcbmNvbnN0IG1heGltaXNlID0gMTM7XHJcbmNvbnN0IHVuTWF4aW1pc2UgPSAxNDtcclxuY29uc3QgdG9nZ2xlTWF4aW1pc2UgPSAxNTtcclxuY29uc3QgbWluaW1pc2UgPSAxNjtcclxuY29uc3QgdW5NaW5pbWlzZSA9IDE3O1xyXG5jb25zdCByZXN0b3JlID0gMTg7XHJcbmNvbnN0IHNob3cgPSAxOTtcclxuY29uc3QgY2xvc2UgPSAyMDtcclxuY29uc3Qgc2V0QmFja2dyb3VuZENvbG91ciA9IDIxO1xyXG5jb25zdCBzZXRSZXNpemFibGUgPSAyMjtcclxuY29uc3Qgd2lkdGggPSAyMztcclxuY29uc3QgaGVpZ2h0ID0gMjQ7XHJcbmNvbnN0IHpvb21JbiA9IDI1O1xyXG5jb25zdCB6b29tT3V0ID0gMjY7XHJcbmNvbnN0IHpvb21SZXNldCA9IDI3O1xyXG5jb25zdCBnZXRab29tTGV2ZWwgPSAyODtcclxuY29uc3Qgc2V0Wm9vbUxldmVsID0gMjk7XHJcblxyXG5jb25zdCB0aGlzV2luZG93ID0gR2V0KCcnKTtcclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVdpbmRvdyhjYWxsKSB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIEdldDogKHdpbmRvd05hbWUpID0+IGNyZWF0ZVdpbmRvdyhuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLldpbmRvdywgd2luZG93TmFtZSkpLFxyXG4gICAgICAgIENlbnRlcjogKCkgPT4gY2FsbChjZW50ZXIpLFxyXG4gICAgICAgIFNldFRpdGxlOiAodGl0bGUpID0+IGNhbGwoc2V0VGl0bGUsIHt0aXRsZX0pLFxyXG4gICAgICAgIEZ1bGxzY3JlZW46ICgpID0+IGNhbGwoZnVsbHNjcmVlbiksXHJcbiAgICAgICAgVW5GdWxsc2NyZWVuOiAoKSA9PiBjYWxsKHVuRnVsbHNjcmVlbiksXHJcbiAgICAgICAgU2V0U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcclxuICAgICAgICBTaXplOiAoKSA9PiBjYWxsKHNpemUpLFxyXG4gICAgICAgIFNldE1heFNpemU6ICh3aWR0aCwgaGVpZ2h0KSA9PiBjYWxsKHNldE1heFNpemUsIHt3aWR0aCwgaGVpZ2h0fSksXHJcbiAgICAgICAgU2V0TWluU2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWluU2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcclxuICAgICAgICBTZXRBbHdheXNPblRvcDogKG9uVG9wKSA9PiBjYWxsKHNldEFsd2F5c09uVG9wLCB7YWx3YXlzT25Ub3A6IG9uVG9wfSksXHJcbiAgICAgICAgU2V0UmVsYXRpdmVQb3NpdGlvbjogKHgsIHkpID0+IGNhbGwoc2V0UmVsYXRpdmVQb3NpdGlvbiwge3gsIHl9KSxcclxuICAgICAgICBSZWxhdGl2ZVBvc2l0aW9uOiAoKSA9PiBjYWxsKHJlbGF0aXZlUG9zaXRpb24pLFxyXG4gICAgICAgIFNjcmVlbjogKCkgPT4gY2FsbChzY3JlZW4pLFxyXG4gICAgICAgIEhpZGU6ICgpID0+IGNhbGwoaGlkZSksXHJcbiAgICAgICAgTWF4aW1pc2U6ICgpID0+IGNhbGwobWF4aW1pc2UpLFxyXG4gICAgICAgIFVuTWF4aW1pc2U6ICgpID0+IGNhbGwodW5NYXhpbWlzZSksXHJcbiAgICAgICAgVG9nZ2xlTWF4aW1pc2U6ICgpID0+IGNhbGwodG9nZ2xlTWF4aW1pc2UpLFxyXG4gICAgICAgIE1pbmltaXNlOiAoKSA9PiBjYWxsKG1pbmltaXNlKSxcclxuICAgICAgICBVbk1pbmltaXNlOiAoKSA9PiBjYWxsKHVuTWluaW1pc2UpLFxyXG4gICAgICAgIFJlc3RvcmU6ICgpID0+IGNhbGwocmVzdG9yZSksXHJcbiAgICAgICAgU2hvdzogKCkgPT4gY2FsbChzaG93KSxcclxuICAgICAgICBDbG9zZTogKCkgPT4gY2FsbChjbG9zZSksXHJcbiAgICAgICAgU2V0QmFja2dyb3VuZENvbG91cjogKHIsIGcsIGIsIGEpID0+IGNhbGwoc2V0QmFja2dyb3VuZENvbG91ciwge3IsIGcsIGIsIGF9KSxcclxuICAgICAgICBTZXRSZXNpemFibGU6IChyZXNpemFibGUpID0+IGNhbGwoc2V0UmVzaXphYmxlLCB7cmVzaXphYmxlfSksXHJcbiAgICAgICAgV2lkdGg6ICgpID0+IGNhbGwod2lkdGgpLFxyXG4gICAgICAgIEhlaWdodDogKCkgPT4gY2FsbChoZWlnaHQpLFxyXG4gICAgICAgIFpvb21JbjogKCkgPT4gY2FsbCh6b29tSW4pLFxyXG4gICAgICAgIFpvb21PdXQ6ICgpID0+IGNhbGwoem9vbU91dCksXHJcbiAgICAgICAgWm9vbVJlc2V0OiAoKSA9PiBjYWxsKHpvb21SZXNldCksXHJcbiAgICAgICAgR2V0Wm9vbUxldmVsOiAoKSA9PiBjYWxsKGdldFpvb21MZXZlbCksXHJcbiAgICAgICAgU2V0Wm9vbUxldmVsOiAoem9vbUxldmVsKSA9PiBjYWxsKHNldFpvb21MZXZlbCwge3pvb21MZXZlbH0pLFxyXG4gICAgfTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIHNwZWNpZmllZCB3aW5kb3cuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSB3aW5kb3dOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHdpbmRvdyB0byBnZXQuXHJcbiAqIEByZXR1cm4ge09iamVjdH0gLSBUaGUgc3BlY2lmaWVkIHdpbmRvdyBvYmplY3QuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gR2V0KHdpbmRvd05hbWUpIHtcclxuICAgIHJldHVybiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENlbnRlcnMgdGhlIHdpbmRvdyBvbiB0aGUgc2NyZWVuLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIENlbnRlcigpIHtcclxuICAgIHRoaXNXaW5kb3cuQ2VudGVyKCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXRzIHRoZSB0aXRsZSBvZiB0aGUgd2luZG93LlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGUgLSBUaGUgdGl0bGUgdG8gc2V0LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldFRpdGxlKHRpdGxlKSB7XHJcbiAgICB0aGlzV2luZG93LlNldFRpdGxlKHRpdGxlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIHdpbmRvdyB0byBmdWxsc2NyZWVuLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEZ1bGxzY3JlZW4oKSB7XHJcbiAgICB0aGlzV2luZG93LkZ1bGxzY3JlZW4oKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIHNpemUgb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgLSBUaGUgaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2V0U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XHJcbiAgICB0aGlzV2luZG93LlNldFNpemUod2lkdGgsIGhlaWdodCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBzaXplIG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2l6ZSgpIHtcclxuICAgIHJldHVybiB0aGlzV2luZG93LlNpemUoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93LlxyXG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGggLSBUaGUgbWF4aW11bSB3aWR0aCBvZiB0aGUgd2luZG93LlxyXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIG1heGltdW0gaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XHJcbiAgICB0aGlzV2luZG93LlNldE1heFNpemUod2lkdGgsIGhlaWdodCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXRzIHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIG1pbmltdW0gd2lkdGggb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodCAtIFRoZSBtaW5pbXVtIGhlaWdodCBvZiB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldE1pblNpemUod2lkdGgsIGhlaWdodCkge1xyXG4gICAgdGhpc1dpbmRvdy5TZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgd2luZG93IHRvIGFsd2F5cyBiZSBvbiB0b3AuXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gb25Ub3AgLSBXaGV0aGVyIHRoZSB3aW5kb3cgc2hvdWxkIGFsd2F5cyBiZSBvbiB0b3AuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2V0QWx3YXlzT25Ub3Aob25Ub3ApIHtcclxuICAgIHRoaXNXaW5kb3cuU2V0QWx3YXlzT25Ub3Aob25Ub3ApO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHggLSBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSB3aW5kb3cncyBwb3NpdGlvbi5cclxuICogQHBhcmFtIHtudW1iZXJ9IHkgLSBUaGUgeS1jb29yZGluYXRlIG9mIHRoZSB3aW5kb3cncyBwb3NpdGlvbi5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTZXRSZWxhdGl2ZVBvc2l0aW9uKHgsIHkpIHtcclxuICAgIHRoaXNXaW5kb3cuU2V0UmVsYXRpdmVQb3NpdGlvbih4LCB5KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gUmVsYXRpdmVQb3NpdGlvbigpIHtcclxuICAgIHJldHVybiB0aGlzV2luZG93LlJlbGF0aXZlUG9zaXRpb24oKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIHNjcmVlbiB0aGF0IHRoZSB3aW5kb3cgaXMgb24uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2NyZWVuKCkge1xyXG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2NyZWVuKCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBIaWRlcyB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XHJcbiAgICB0aGlzV2luZG93LkhpZGUoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE1heGltaXNlcyB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIE1heGltaXNlKCkge1xyXG4gICAgdGhpc1dpbmRvdy5NYXhpbWlzZSgpO1xyXG59XHJcblxyXG4vKipcclxuICogVW4tbWF4aW1pc2VzIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gVW5NYXhpbWlzZSgpIHtcclxuICAgIHRoaXNXaW5kb3cuVW5NYXhpbWlzZSgpO1xyXG59XHJcblxyXG4vKipcclxuICogVG9nZ2xlcyB0aGUgbWF4aW1pc2F0aW9uIG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gVG9nZ2xlTWF4aW1pc2UoKSB7XHJcbiAgICB0aGlzV2luZG93LlRvZ2dsZU1heGltaXNlKCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBNaW5pbWlzZXMgdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBNaW5pbWlzZSgpIHtcclxuICAgIHRoaXNXaW5kb3cuTWluaW1pc2UoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFVuLW1pbmltaXNlcyB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFVuTWluaW1pc2UoKSB7XHJcbiAgICB0aGlzV2luZG93LlVuTWluaW1pc2UoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlc3RvcmVzIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gUmVzdG9yZSgpIHtcclxuICAgIHRoaXNXaW5kb3cuUmVzdG9yZSgpO1xyXG59XHJcblxyXG4vKipcclxuICogU2hvd3MgdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTaG93KCkge1xyXG4gICAgdGhpc1dpbmRvdy5TaG93KCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDbG9zZXMgdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBDbG9zZSgpIHtcclxuICAgIHRoaXNXaW5kb3cuQ2xvc2UoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIGJhY2tncm91bmQgY29sb3VyIG9mIHRoZSB3aW5kb3cuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSByIC0gVGhlIHJlZCBjb21wb25lbnQgb2YgdGhlIGNvbG91ci5cclxuICogQHBhcmFtIHtudW1iZXJ9IGcgLSBUaGUgZ3JlZW4gY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIC0gVGhlIGJsdWUgY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIC0gVGhlIGFscGhhIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldEJhY2tncm91bmRDb2xvdXIociwgZywgYiwgYSkge1xyXG4gICAgdGhpc1dpbmRvdy5TZXRCYWNrZ3JvdW5kQ29sb3VyKHIsIGcsIGIsIGEpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgcmVzaXphYmxlLlxyXG4gKiBAcGFyYW0ge2Jvb2xlYW59IHJlc2l6YWJsZSAtIFdoZXRoZXIgdGhlIHdpbmRvdyBzaG91bGQgYmUgcmVzaXphYmxlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldFJlc2l6YWJsZShyZXNpemFibGUpIHtcclxuICAgIHRoaXNXaW5kb3cuU2V0UmVzaXphYmxlKHJlc2l6YWJsZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSB3aWR0aCBvZiB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpZHRoKCkge1xyXG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuV2lkdGgoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEhlaWdodCgpIHtcclxuICAgIHJldHVybiB0aGlzV2luZG93LkhlaWdodCgpO1xyXG59XHJcblxyXG4vKipcclxuICogWm9vbXMgaW4gdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBab29tSW4oKSB7XHJcbiAgICB0aGlzV2luZG93Llpvb21JbigpO1xyXG59XHJcblxyXG4vKipcclxuICogWm9vbXMgb3V0IHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gWm9vbU91dCgpIHtcclxuICAgIHRoaXNXaW5kb3cuWm9vbU91dCgpO1xyXG59XHJcblxyXG4vKipcclxuICogUmVzZXRzIHRoZSB6b29tIG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gWm9vbVJlc2V0KCkge1xyXG4gICAgdGhpc1dpbmRvdy5ab29tUmVzZXQoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBHZXRab29tTGV2ZWwoKSB7XHJcbiAgICByZXR1cm4gdGhpc1dpbmRvdy5HZXRab29tTGV2ZWwoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHpvb21MZXZlbCAtIFRoZSB6b29tIGxldmVsIHRvIHNldC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTZXRab29tTGV2ZWwoem9vbUxldmVsKSB7XHJcbiAgICB0aGlzV2luZG93LlNldFpvb21MZXZlbCh6b29tTGV2ZWwpO1xyXG59XHJcbiIsICJcclxuaW1wb3J0IHtFbWl0LCBXYWlsc0V2ZW50fSBmcm9tIFwiLi9ldmVudHNcIjtcclxuaW1wb3J0IHtRdWVzdGlvbn0gZnJvbSBcIi4vZGlhbG9nc1wiO1xyXG5pbXBvcnQge0dldH0gZnJvbSBcIi4vd2luZG93XCI7XHJcbmltcG9ydCB7T3BlblVSTH0gZnJvbSBcIi4vYnJvd3NlclwiO1xyXG5pbXBvcnQge2RlYnVnTG9nfSBmcm9tIFwiLi9sb2dcIjtcclxuXHJcbi8qKlxyXG4gKiBTZW5kcyBhbiBldmVudCB3aXRoIHRoZSBnaXZlbiBuYW1lIGFuZCBvcHRpb25hbCBkYXRhLlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHNlbmQuXHJcbiAqIEBwYXJhbSB7YW55fSBbZGF0YT1udWxsXSAtIE9wdGlvbmFsIGRhdGEgdG8gc2VuZCBhbG9uZyB3aXRoIHRoZSBldmVudC5cclxuICpcclxuICogQHJldHVybiB7dm9pZH1cclxuICovXHJcbmZ1bmN0aW9uIHNlbmRFdmVudChldmVudE5hbWUsIGRhdGE9bnVsbCkge1xyXG4gICAgbGV0IGV2ZW50ID0gbmV3IFdhaWxzRXZlbnQoZXZlbnROYW1lLCBkYXRhKTtcclxuICAgIEVtaXQoZXZlbnQpO1xyXG59XHJcblxyXG4vKipcclxuICogQWRkcyBldmVudCBsaXN0ZW5lcnMgdG8gZWxlbWVudHMgd2l0aCBgd21sLWV2ZW50YCBhdHRyaWJ1dGUuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3ZvaWR9XHJcbiAqL1xyXG5mdW5jdGlvbiBhZGRXTUxFdmVudExpc3RlbmVycygpIHtcclxuICAgIGNvbnN0IGVsZW1lbnRzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnW3dtbC1ldmVudF0nKTtcclxuICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHtcclxuICAgICAgICBjb25zdCBldmVudFR5cGUgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWV2ZW50Jyk7XHJcbiAgICAgICAgY29uc3QgY29uZmlybSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtY29uZmlybScpO1xyXG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XHJcblxyXG4gICAgICAgIGxldCBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcclxuICAgICAgICAgICAgICAgIFF1ZXN0aW9uKHtUaXRsZTogXCJDb25maXJtXCIsIE1lc3NhZ2U6Y29uZmlybSwgRGV0YWNoZWQ6IGZhbHNlLCBCdXR0b25zOlt7TGFiZWw6XCJZZXNcIn0se0xhYmVsOlwiTm9cIiwgSXNEZWZhdWx0OnRydWV9XX0pLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT09IFwiTm9cIikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kRXZlbnQoZXZlbnRUeXBlKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBzZW5kRXZlbnQoZXZlbnRUeXBlKTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvLyBSZW1vdmUgZXhpc3RpbmcgbGlzdGVuZXJzXHJcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcclxuXHJcbiAgICAgICAgLy8gQWRkIG5ldyBsaXN0ZW5lclxyXG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBDYWxscyBhIG1ldGhvZCBvbiBhIHNwZWNpZmllZCB3aW5kb3cuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSB3aW5kb3dOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHdpbmRvdyB0byBjYWxsIHRoZSBtZXRob2Qgb24uXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2QgLSBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXHJcbiAqL1xyXG5mdW5jdGlvbiBjYWxsV2luZG93TWV0aG9kKHdpbmRvd05hbWUsIG1ldGhvZCkge1xyXG4gICAgbGV0IHRhcmdldFdpbmRvdyA9IEdldCh3aW5kb3dOYW1lKTtcclxuICAgIGxldCBtZXRob2RNYXAgPSBXaW5kb3dNZXRob2RzKHRhcmdldFdpbmRvdyk7XHJcbiAgICBpZiAoIW1ldGhvZE1hcC5oYXMobWV0aG9kKSkge1xyXG4gICAgICAgIGNvbnNvbGUubG9nKFwiV2luZG93IG1ldGhvZCBcIiArIG1ldGhvZCArIFwiIG5vdCBmb3VuZFwiKTtcclxuICAgIH1cclxuICAgIHRyeSB7XHJcbiAgICAgICAgbWV0aG9kTWFwLmdldChtZXRob2QpKCk7XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIGNhbGxpbmcgd2luZG93IG1ldGhvZCAnXCIgKyBtZXRob2QgKyBcIic6IFwiICsgZSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBBZGRzIHdpbmRvdyBsaXN0ZW5lcnMgZm9yIGVsZW1lbnRzIHdpdGggdGhlICd3bWwtd2luZG93JyBhdHRyaWJ1dGUuXHJcbiAqIFJlbW92ZXMgYW55IGV4aXN0aW5nIGxpc3RlbmVycyBiZWZvcmUgYWRkaW5nIG5ldyBvbmVzLlxyXG4gKlxyXG4gKiBAcmV0dXJuIHt2b2lkfVxyXG4gKi9cclxuZnVuY3Rpb24gYWRkV01MV2luZG93TGlzdGVuZXJzKCkge1xyXG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLXdpbmRvd10nKTtcclxuICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHtcclxuICAgICAgICBjb25zdCB3aW5kb3dNZXRob2QgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXdpbmRvdycpO1xyXG4gICAgICAgIGNvbnN0IGNvbmZpcm0gPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWNvbmZpcm0nKTtcclxuICAgICAgICBjb25zdCB0cmlnZ2VyID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC10cmlnZ2VyJykgfHwgJ2NsaWNrJztcclxuICAgICAgICBjb25zdCB0YXJnZXRXaW5kb3cgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRhcmdldC13aW5kb3cnKSB8fCAnJztcclxuXHJcbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAoY29uZmlybSkge1xyXG4gICAgICAgICAgICAgICAgUXVlc3Rpb24oe1RpdGxlOiBcIkNvbmZpcm1cIiwgTWVzc2FnZTpjb25maXJtLCBCdXR0b25zOlt7TGFiZWw6XCJZZXNcIn0se0xhYmVsOlwiTm9cIiwgSXNEZWZhdWx0OnRydWV9XX0pLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT09IFwiTm9cIikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYWxsV2luZG93TWV0aG9kKHRhcmdldFdpbmRvdywgd2luZG93TWV0aG9kKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYWxsV2luZG93TWV0aG9kKHRhcmdldFdpbmRvdywgd2luZG93TWV0aG9kKTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvLyBSZW1vdmUgZXhpc3RpbmcgbGlzdGVuZXJzXHJcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcclxuXHJcbiAgICAgICAgLy8gQWRkIG5ldyBsaXN0ZW5lclxyXG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEFkZHMgYSBsaXN0ZW5lciB0byBlbGVtZW50cyB3aXRoIHRoZSAnd21sLW9wZW51cmwnIGF0dHJpYnV0ZS5cclxuICogV2hlbiB0aGUgc3BlY2lmaWVkIHRyaWdnZXIgZXZlbnQgaXMgZmlyZWQgb24gYW55IG9mIHRoZXNlIGVsZW1lbnRzLFxyXG4gKiB0aGUgbGlzdGVuZXIgd2lsbCBvcGVuIHRoZSBVUkwgc3BlY2lmaWVkIGJ5IHRoZSAnd21sLW9wZW51cmwnIGF0dHJpYnV0ZS5cclxuICogSWYgYSAnd21sLWNvbmZpcm0nIGF0dHJpYnV0ZSBpcyBwcm92aWRlZCwgYSBjb25maXJtYXRpb24gZGlhbG9nIHdpbGwgYmUgZGlzcGxheWVkLFxyXG4gKiBhbmQgdGhlIFVSTCB3aWxsIG9ubHkgYmUgb3BlbmVkIGlmIHRoZSB1c2VyIGNvbmZpcm1zLlxyXG4gKlxyXG4gKiBAcmV0dXJuIHt2b2lkfVxyXG4gKi9cclxuZnVuY3Rpb24gYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpIHtcclxuICAgIGNvbnN0IGVsZW1lbnRzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnW3dtbC1vcGVudXJsXScpO1xyXG4gICAgZWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbiAoZWxlbWVudCkge1xyXG4gICAgICAgIGNvbnN0IHVybCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtb3BlbnVybCcpO1xyXG4gICAgICAgIGNvbnN0IGNvbmZpcm0gPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWNvbmZpcm0nKTtcclxuICAgICAgICBjb25zdCB0cmlnZ2VyID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC10cmlnZ2VyJykgfHwgXCJjbGlja1wiO1xyXG5cclxuICAgICAgICBsZXQgY2FsbGJhY2sgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChjb25maXJtKSB7XHJcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIEJ1dHRvbnM6W3tMYWJlbDpcIlllc1wifSx7TGFiZWw6XCJOb1wiLCBJc0RlZmF1bHQ6dHJ1ZX1dfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPT0gXCJOb1wiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZvaWQgT3BlblVSTCh1cmwpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHZvaWQgT3BlblVSTCh1cmwpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8vIFJlbW92ZSBleGlzdGluZyBsaXN0ZW5lcnNcclxuICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xyXG5cclxuICAgICAgICAvLyBBZGQgbmV3IGxpc3RlbmVyXHJcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogUmVsb2FkcyB0aGUgV01MIHBhZ2UgYnkgYWRkaW5nIG5lY2Vzc2FyeSBldmVudCBsaXN0ZW5lcnMgYW5kIGJyb3dzZXIgbGlzdGVuZXJzLlxyXG4gKlxyXG4gKiBAcmV0dXJuIHt2b2lkfVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFJlbG9hZCgpIHtcclxuICAgIGlmKERFQlVHKSB7XHJcbiAgICAgICAgZGVidWdMb2coXCJSZWxvYWRpbmcgV01MXCIpO1xyXG4gICAgfVxyXG4gICAgYWRkV01MRXZlbnRMaXN0ZW5lcnMoKTtcclxuICAgIGFkZFdNTFdpbmRvd0xpc3RlbmVycygpO1xyXG4gICAgYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpO1xyXG59XHJcblxyXG4vKipcclxuICogUmV0dXJucyBhIG1hcCBvZiBhbGwgbWV0aG9kcyBpbiB0aGUgY3VycmVudCB3aW5kb3cuXHJcbiAqIEByZXR1cm5zIHtNYXB9IC0gQSBtYXAgb2Ygd2luZG93IG1ldGhvZHMuXHJcbiAqL1xyXG5mdW5jdGlvbiBXaW5kb3dNZXRob2RzKHRhcmdldFdpbmRvdykge1xyXG4gICAgLy8gQ3JlYXRlIGEgbmV3IG1hcCB0byBzdG9yZSBtZXRob2RzXHJcbiAgICBsZXQgcmVzdWx0ID0gbmV3IE1hcCgpO1xyXG5cclxuICAgIC8vIEl0ZXJhdGUgb3ZlciBhbGwgcHJvcGVydGllcyBvZiB0aGUgd2luZG93IG9iamVjdFxyXG4gICAgZm9yIChsZXQgbWV0aG9kIGluIHRhcmdldFdpbmRvdykge1xyXG4gICAgICAgIC8vIENoZWNrIGlmIHRoZSBwcm9wZXJ0eSBpcyBpbmRlZWQgYSBtZXRob2QgKGZ1bmN0aW9uKVxyXG4gICAgICAgIGlmKHR5cGVvZiB0YXJnZXRXaW5kb3dbbWV0aG9kXSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgICAvLyBBZGQgdGhlIG1ldGhvZCB0byB0aGUgbWFwXHJcbiAgICAgICAgICAgIHJlc3VsdC5zZXQobWV0aG9kLCB0YXJnZXRXaW5kb3dbbWV0aG9kXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgIH1cclxuICAgIC8vIFJldHVybiB0aGUgbWFwIG9mIHdpbmRvdyBtZXRob2RzXHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59IiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7aW1wb3J0KFwiLi90eXBlc1wiKS5XYWlsc0V2ZW50fSBXYWlsc0V2ZW50XHJcbiAqL1xyXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcblxyXG5pbXBvcnQge0V2ZW50VHlwZXN9IGZyb20gXCIuL2V2ZW50X3R5cGVzXCI7XHJcbmV4cG9ydCBjb25zdCBUeXBlcyA9IEV2ZW50VHlwZXM7XHJcblxyXG4vLyBTZXR1cFxyXG53aW5kb3cuX3dhaWxzID0gd2luZG93Ll93YWlscyB8fCB7fTtcclxud2luZG93Ll93YWlscy5kaXNwYXRjaFdhaWxzRXZlbnQgPSBkaXNwYXRjaFdhaWxzRXZlbnQ7XHJcblxyXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5FdmVudHMsICcnKTtcclxuY29uc3QgRW1pdE1ldGhvZCA9IDA7XHJcbmNvbnN0IGV2ZW50TGlzdGVuZXJzID0gbmV3IE1hcCgpO1xyXG5cclxuY2xhc3MgTGlzdGVuZXIge1xyXG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XHJcbiAgICAgICAgdGhpcy5ldmVudE5hbWUgPSBldmVudE5hbWU7XHJcbiAgICAgICAgdGhpcy5tYXhDYWxsYmFja3MgPSBtYXhDYWxsYmFja3MgfHwgLTE7XHJcbiAgICAgICAgdGhpcy5DYWxsYmFjayA9IChkYXRhKSA9PiB7XHJcbiAgICAgICAgICAgIGNhbGxiYWNrKGRhdGEpO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhDYWxsYmFja3MgPT09IC0xKSByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIHRoaXMubWF4Q2FsbGJhY2tzIC09IDE7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heENhbGxiYWNrcyA9PT0gMDtcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgV2FpbHNFdmVudCB7XHJcbiAgICBjb25zdHJ1Y3RvcihuYW1lLCBkYXRhID0gbnVsbCkge1xyXG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XHJcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIHNldHVwKCkge1xyXG59XHJcblxyXG5mdW5jdGlvbiBkaXNwYXRjaFdhaWxzRXZlbnQoZXZlbnQpIHtcclxuICAgIGxldCBsaXN0ZW5lcnMgPSBldmVudExpc3RlbmVycy5nZXQoZXZlbnQubmFtZSk7XHJcbiAgICBpZiAobGlzdGVuZXJzKSB7XHJcbiAgICAgICAgbGV0IHRvUmVtb3ZlID0gbGlzdGVuZXJzLmZpbHRlcihsaXN0ZW5lciA9PiB7XHJcbiAgICAgICAgICAgIGxldCByZW1vdmUgPSBsaXN0ZW5lci5DYWxsYmFjayhldmVudCk7XHJcbiAgICAgICAgICAgIGlmIChyZW1vdmUpIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGlmICh0b1JlbW92ZS5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVycy5maWx0ZXIobCA9PiAhdG9SZW1vdmUuaW5jbHVkZXMobCkpO1xyXG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkgZXZlbnRMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50Lm5hbWUpO1xyXG4gICAgICAgICAgICBlbHNlIGV2ZW50TGlzdGVuZXJzLnNldChldmVudC5uYW1lLCBsaXN0ZW5lcnMpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzIGZvciBhIHNwZWNpZmljIGV2ZW50LlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmb3IuXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3MgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdGhlIGNhbGxiYWNrIGNhbiBiZSBjYWxsZWQgZm9yIHRoZSBldmVudC4gT25jZSB0aGUgbWF4aW11bSBudW1iZXIgaXMgcmVhY2hlZCwgdGhlIGNhbGxiYWNrIHdpbGwgbm8gbG9uZ2VyIGJlIGNhbGxlZC5cclxuICpcclxuIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpIHtcclxuICAgIGxldCBsaXN0ZW5lcnMgPSBldmVudExpc3RlbmVycy5nZXQoZXZlbnROYW1lKSB8fCBbXTtcclxuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xyXG4gICAgbGlzdGVuZXJzLnB1c2godGhpc0xpc3RlbmVyKTtcclxuICAgIGV2ZW50TGlzdGVuZXJzLnNldChldmVudE5hbWUsIGxpc3RlbmVycyk7XHJcbiAgICByZXR1cm4gKCkgPT4gbGlzdGVuZXJPZmYodGhpc0xpc3RlbmVyKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdGVycyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIHNwZWNpZmllZCBldmVudCBvY2N1cnMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkLiBJdCB0YWtlcyBubyBwYXJhbWV0ZXJzLlxyXG4gKiBAcmV0dXJuIHtmdW5jdGlvbn0gLSBBIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCB3aWxsIHVucmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZyb20gdGhlIGV2ZW50LiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gT24oZXZlbnROYW1lLCBjYWxsYmFjaykgeyByZXR1cm4gT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAtMSk7IH1cclxuXHJcbi8qKlxyXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmx5IG9uY2UgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGV2ZW50IG9jY3Vycy5cclxuICogQHJldHVybiB7ZnVuY3Rpb259IC0gQSBmdW5jdGlvbiB0aGF0LCB3aGVuIGNhbGxlZCwgd2lsbCB1bnJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmcm9tIHRoZSBldmVudC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHsgcmV0dXJuIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgMSk7IH1cclxuXHJcbi8qKlxyXG4gKiBSZW1vdmVzIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIgZnJvbSB0aGUgZXZlbnQgbGlzdGVuZXJzIGNvbGxlY3Rpb24uXHJcbiAqIElmIGFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBldmVudCBhcmUgcmVtb3ZlZCwgdGhlIGV2ZW50IGtleSBpcyBkZWxldGVkIGZyb20gdGhlIGNvbGxlY3Rpb24uXHJcbiAqXHJcbiAqIEBwYXJhbSB7T2JqZWN0fSBsaXN0ZW5lciAtIFRoZSBsaXN0ZW5lciB0byBiZSByZW1vdmVkLlxyXG4gKi9cclxuZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXIpIHtcclxuICAgIGNvbnN0IGV2ZW50TmFtZSA9IGxpc3RlbmVyLmV2ZW50TmFtZTtcclxuICAgIGxldCBsaXN0ZW5lcnMgPSBldmVudExpc3RlbmVycy5nZXQoZXZlbnROYW1lKS5maWx0ZXIobCA9PiBsICE9PSBsaXN0ZW5lcik7XHJcbiAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkgZXZlbnRMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSk7XHJcbiAgICBlbHNlIGV2ZW50TGlzdGVuZXJzLnNldChldmVudE5hbWUsIGxpc3RlbmVycyk7XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogUmVtb3ZlcyBldmVudCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQgbmFtZXMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGxpc3RlbmVycyBmb3IuXHJcbiAqIEBwYXJhbSB7Li4uc3RyaW5nfSBhZGRpdGlvbmFsRXZlbnROYW1lcyAtIEFkZGl0aW9uYWwgZXZlbnQgbmFtZXMgdG8gcmVtb3ZlIGxpc3RlbmVycyBmb3IuXHJcbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBPZmYoZXZlbnROYW1lLCAuLi5hZGRpdGlvbmFsRXZlbnROYW1lcykge1xyXG4gICAgbGV0IGV2ZW50c1RvUmVtb3ZlID0gW2V2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXNdO1xyXG4gICAgZXZlbnRzVG9SZW1vdmUuZm9yRWFjaChldmVudE5hbWUgPT4gZXZlbnRMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSkpO1xyXG59XHJcbi8qKlxyXG4gKiBSZW1vdmVzIGFsbCBldmVudCBsaXN0ZW5lcnMuXHJcbiAqXHJcbiAqIEBmdW5jdGlvbiBPZmZBbGxcclxuICogQHJldHVybnMge3ZvaWR9XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gT2ZmQWxsKCkgeyBldmVudExpc3RlbmVycy5jbGVhcigpOyB9XHJcblxyXG4vKipcclxuICogRW1pdHMgYW4gZXZlbnQgdXNpbmcgdGhlIGdpdmVuIGV2ZW50IG5hbWUuXHJcbiAqXHJcbiAqIEBwYXJhbSB7V2FpbHNFdmVudH0gZXZlbnQgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdC5cclxuICogQHJldHVybnMge2FueX0gLSBUaGUgcmVzdWx0IG9mIHRoZSBlbWl0dGVkIGV2ZW50LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEVtaXQoZXZlbnQpIHsgcmV0dXJuIGNhbGwoRW1pdE1ldGhvZCwgZXZlbnQpOyB9XHJcbiIsICJcbmV4cG9ydCBjb25zdCBFdmVudFR5cGVzID0ge1xuXHRXaW5kb3dzOiB7XG5cdFx0U3lzdGVtVGhlbWVDaGFuZ2VkOiBcIndpbmRvd3M6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdFx0QVBNUG93ZXJTdGF0dXNDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclN0YXR1c0NoYW5nZVwiLFxuXHRcdEFQTVN1c3BlbmQ6IFwid2luZG93czpBUE1TdXNwZW5kXCIsXG5cdFx0QVBNUmVzdW1lQXV0b21hdGljOiBcIndpbmRvd3M6QVBNUmVzdW1lQXV0b21hdGljXCIsXG5cdFx0QVBNUmVzdW1lU3VzcGVuZDogXCJ3aW5kb3dzOkFQTVJlc3VtZVN1c3BlbmRcIixcblx0XHRBUE1Qb3dlclNldHRpbmdDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclNldHRpbmdDaGFuZ2VcIixcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwid2luZG93czpBcHBsaWNhdGlvblN0YXJ0ZWRcIixcblx0XHRXZWJWaWV3TmF2aWdhdGlvbkNvbXBsZXRlZDogXCJ3aW5kb3dzOldlYlZpZXdOYXZpZ2F0aW9uQ29tcGxldGVkXCIsXG5cdFx0V2luZG93SW5hY3RpdmU6IFwid2luZG93czpXaW5kb3dJbmFjdGl2ZVwiLFxuXHRcdFdpbmRvd0FjdGl2ZTogXCJ3aW5kb3dzOldpbmRvd0FjdGl2ZVwiLFxuXHRcdFdpbmRvd0NsaWNrQWN0aXZlOiBcIndpbmRvd3M6V2luZG93Q2xpY2tBY3RpdmVcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcIndpbmRvd3M6V2luZG93RnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1VuRnVsbHNjcmVlbjogXCJ3aW5kb3dzOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwid2luZG93czpXaW5kb3dSZXN0b3JlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwid2luZG93czpXaW5kb3dNaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWluaW1pc2U6IFwid2luZG93czpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2U6IFwid2luZG93czpXaW5kb3dDbG9zZVwiLFxuXHRcdFdpbmRvd1NldEZvY3VzOiBcIndpbmRvd3M6V2luZG93U2V0Rm9jdXNcIixcblx0XHRXaW5kb3dLaWxsRm9jdXM6IFwid2luZG93czpXaW5kb3dLaWxsRm9jdXNcIixcblx0XHRXaW5kb3dEcmFnRHJvcDogXCJ3aW5kb3dzOldpbmRvd0RyYWdEcm9wXCIsXG5cdFx0V2luZG93RHJhZ0VudGVyOiBcIndpbmRvd3M6V2luZG93RHJhZ0VudGVyXCIsXG5cdFx0V2luZG93RHJhZ0xlYXZlOiBcIndpbmRvd3M6V2luZG93RHJhZ0xlYXZlXCIsXG5cdFx0V2luZG93RHJhZ092ZXI6IFwid2luZG93czpXaW5kb3dEcmFnT3ZlclwiLFxuXHR9LFxuXHRNYWM6IHtcblx0XHRBcHBsaWNhdGlvbkRpZEJlY29tZUFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUVmZmVjdGl2ZUFwcGVhcmFuY2VcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUljb246IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlSWNvblwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU2NyZWVuUGFyYW1ldGVyc1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uXCIsXG5cdFx0QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmc6IFwibWFjOkFwcGxpY2F0aW9uRGlkRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25EaWRIaWRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZEhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFJlc2lnbkFjdGl2ZU5vdGlmaWNhdGlvbjogXCJtYWM6QXBwbGljYXRpb25EaWRSZXNpZ25BY3RpdmVOb3RpZmljYXRpb25cIixcblx0XHRBcHBsaWNhdGlvbkRpZFVuaGlkZTogXCJtYWM6QXBwbGljYXRpb25EaWRVbmhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25EaWRVcGRhdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxCZWNvbWVBY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbEJlY29tZUFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEZpbmlzaExhdW5jaGluZzogXCJtYWM6QXBwbGljYXRpb25XaWxsRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsSGlkZTogXCJtYWM6QXBwbGljYXRpb25XaWxsSGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFJlc2lnbkFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVGVybWluYXRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxVbmhpZGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFVuaGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsVXBkYXRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZTogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZSFcIixcblx0XHRBcHBsaWNhdGlvblNob3VsZEhhbmRsZVJlb3BlbjogXCJtYWM6QXBwbGljYXRpb25TaG91bGRIYW5kbGVSZW9wZW4hXCIsXG5cdFx0V2luZG93RGlkQmVjb21lS2V5OiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dEaWRCZWNvbWVNYWluOiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVNYWluXCIsXG5cdFx0V2luZG93RGlkQmVnaW5TaGVldDogXCJtYWM6V2luZG93RGlkQmVnaW5TaGVldFwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUFscGhhOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VBbHBoYVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUJhY2tpbmdMb2NhdGlvbjogXCJtYWM6V2luZG93RGlkQ2hhbmdlQmFja2luZ0xvY2F0aW9uXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQmFja2luZ1Byb3BlcnRpZXM6IFwibWFjOldpbmRvd0RpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOldpbmRvd0RpZENoYW5nZU9jY2x1c2lvblN0YXRlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW46IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2U6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2VQcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5TcGFjZVByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTaGFyaW5nVHlwZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2hhcmluZ1R5cGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUaXRsZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVGl0bGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUb29sYmFyOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VUb29sYmFyXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd0RpZERlbWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dEaWRFbmRTaGVldDogXCJtYWM6V2luZG93RGlkRW5kU2hlZXRcIixcblx0XHRXaW5kb3dEaWRFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd0RpZEVudGVyRnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dEaWRFeGl0RnVsbFNjcmVlbjogXCJtYWM6V2luZG93RGlkRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEV4aXRWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd0RpZEV4cG9zZTogXCJtYWM6V2luZG93RGlkRXhwb3NlXCIsXG5cdFx0V2luZG93RGlkRm9jdXM6IFwibWFjOldpbmRvd0RpZEZvY3VzXCIsXG5cdFx0V2luZG93RGlkTWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJtYWM6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRPcmRlck9mZlNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd0RpZE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dEaWRSZXNpZ25LZXk6IFwibWFjOldpbmRvd0RpZFJlc2lnbktleVwiLFxuXHRcdFdpbmRvd0RpZFJlc2lnbk1haW46IFwibWFjOldpbmRvd0RpZFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwibWFjOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZTogXCJtYWM6V2luZG93RGlkVXBkYXRlXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd0RpZFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRpdGxlOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVRvb2xiYXJcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5XCIsXG5cdFx0V2luZG93U2hvdWxkQ2xvc2U6IFwibWFjOldpbmRvd1Nob3VsZENsb3NlIVwiLFxuXHRcdFdpbmRvd1dpbGxCZWNvbWVLZXk6IFwibWFjOldpbmRvd1dpbGxCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dXaWxsQmVjb21lTWFpbjogXCJtYWM6V2luZG93V2lsbEJlY29tZU1haW5cIixcblx0XHRXaW5kb3dXaWxsQmVnaW5TaGVldDogXCJtYWM6V2luZG93V2lsbEJlZ2luU2hlZXRcIixcblx0XHRXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93V2lsbENsb3NlOiBcIm1hYzpXaW5kb3dXaWxsQ2xvc2VcIixcblx0XHRXaW5kb3dXaWxsRGVtaW5pYXR1cml6ZTogXCJtYWM6V2luZG93V2lsbERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd1dpbGxFbnRlclZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEV4aXRGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyOiBcIm1hYzpXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsRm9jdXNcIixcblx0XHRXaW5kb3dXaWxsTWluaWF0dXJpemU6IFwibWFjOldpbmRvd1dpbGxNaW5pYXR1cml6ZVwiLFxuXHRcdFdpbmRvd1dpbGxNb3ZlOiBcIm1hYzpXaW5kb3dXaWxsTW92ZVwiLFxuXHRcdFdpbmRvd1dpbGxPcmRlck9mZlNjcmVlbjogXCJtYWM6V2luZG93V2lsbE9yZGVyT2ZmU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd1dpbGxPcmRlck9uU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbFJlc2lnbk1haW46IFwibWFjOldpbmRvd1dpbGxSZXNpZ25NYWluXCIsXG5cdFx0V2luZG93V2lsbFJlc2l6ZTogXCJtYWM6V2luZG93V2lsbFJlc2l6ZVwiLFxuXHRcdFdpbmRvd1dpbGxVbmZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsVW5mb2N1c1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVBbHBoYVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3I6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXM6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllc1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVTaGFkb3dcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlVGl0bGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVUb29sYmFyOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVG9vbGJhclwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd1dpbGxVc2VTdGFuZGFyZEZyYW1lOiBcIm1hYzpXaW5kb3dXaWxsVXNlU3RhbmRhcmRGcmFtZVwiLFxuXHRcdE1lbnVXaWxsT3BlbjogXCJtYWM6TWVudVdpbGxPcGVuXCIsXG5cdFx0TWVudURpZE9wZW46IFwibWFjOk1lbnVEaWRPcGVuXCIsXG5cdFx0TWVudURpZENsb3NlOiBcIm1hYzpNZW51RGlkQ2xvc2VcIixcblx0XHRNZW51V2lsbFNlbmRBY3Rpb246IFwibWFjOk1lbnVXaWxsU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVXaWxsSGlnaGxpZ2h0SXRlbTogXCJtYWM6TWVudVdpbGxIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudURpZEhpZ2hsaWdodEl0ZW06IFwibWFjOk1lbnVEaWRIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudVdpbGxEaXNwbGF5SXRlbTogXCJtYWM6TWVudVdpbGxEaXNwbGF5SXRlbVwiLFxuXHRcdE1lbnVEaWREaXNwbGF5SXRlbTogXCJtYWM6TWVudURpZERpc3BsYXlJdGVtXCIsXG5cdFx0TWVudVdpbGxBZGRJdGVtOiBcIm1hYzpNZW51V2lsbEFkZEl0ZW1cIixcblx0XHRNZW51RGlkQWRkSXRlbTogXCJtYWM6TWVudURpZEFkZEl0ZW1cIixcblx0XHRNZW51V2lsbFJlbW92ZUl0ZW06IFwibWFjOk1lbnVXaWxsUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVEaWRSZW1vdmVJdGVtOiBcIm1hYzpNZW51RGlkUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVXaWxsQmVnaW5UcmFja2luZzogXCJtYWM6TWVudVdpbGxCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudURpZEJlZ2luVHJhY2tpbmc6IFwibWFjOk1lbnVEaWRCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxFbmRUcmFja2luZzogXCJtYWM6TWVudVdpbGxFbmRUcmFja2luZ1wiLFxuXHRcdE1lbnVEaWRFbmRUcmFja2luZzogXCJtYWM6TWVudURpZEVuZFRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxVcGRhdGU6IFwibWFjOk1lbnVXaWxsVXBkYXRlXCIsXG5cdFx0TWVudURpZFVwZGF0ZTogXCJtYWM6TWVudURpZFVwZGF0ZVwiLFxuXHRcdE1lbnVXaWxsUG9wVXA6IFwibWFjOk1lbnVXaWxsUG9wVXBcIixcblx0XHRNZW51RGlkUG9wVXA6IFwibWFjOk1lbnVEaWRQb3BVcFwiLFxuXHRcdE1lbnVXaWxsU2VuZEFjdGlvblRvSXRlbTogXCJtYWM6TWVudVdpbGxTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0TWVudURpZFNlbmRBY3Rpb25Ub0l0ZW06IFwibWFjOk1lbnVEaWRTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0V2ViVmlld0RpZFN0YXJ0UHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkU3RhcnRQcm92aXNpb25hbE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZENvbW1pdE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRDb21taXROYXZpZ2F0aW9uXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZFwiLFxuXHRcdFdpbmRvd0ZpbGVEcmFnZ2luZ1BlcmZvcm1lZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nUGVyZm9ybWVkXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRXhpdGVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdFeGl0ZWRcIixcblx0fSxcblx0TGludXg6IHtcblx0XHRTeXN0ZW1UaGVtZUNoYW5nZWQ6IFwibGludXg6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdH0sXG5cdENvbW1vbjoge1xuXHRcdEFwcGxpY2F0aW9uU3RhcnRlZDogXCJjb21tb246QXBwbGljYXRpb25TdGFydGVkXCIsXG5cdFx0V2luZG93TWF4aW1pc2U6IFwiY29tbW9uOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJjb21tb246V2luZG93VW5NYXhpbWlzZVwiLFxuXHRcdFdpbmRvd0Z1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd0Z1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dVbkZ1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwiY29tbW9uOldpbmRvd1Jlc3RvcmVcIixcblx0XHRXaW5kb3dNaW5pbWlzZTogXCJjb21tb246V2luZG93TWluaW1pc2VcIixcblx0XHRXaW5kb3dVbk1pbmltaXNlOiBcImNvbW1vbjpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2luZzogXCJjb21tb246V2luZG93Q2xvc2luZ1wiLFxuXHRcdFdpbmRvd1pvb206IFwiY29tbW9uOldpbmRvd1pvb21cIixcblx0XHRXaW5kb3dab29tSW46IFwiY29tbW9uOldpbmRvd1pvb21JblwiLFxuXHRcdFdpbmRvd1pvb21PdXQ6IFwiY29tbW9uOldpbmRvd1pvb21PdXRcIixcblx0XHRXaW5kb3dab29tUmVzZXQ6IFwiY29tbW9uOldpbmRvd1pvb21SZXNldFwiLFxuXHRcdFdpbmRvd0ZvY3VzOiBcImNvbW1vbjpXaW5kb3dGb2N1c1wiLFxuXHRcdFdpbmRvd0xvc3RGb2N1czogXCJjb21tb246V2luZG93TG9zdEZvY3VzXCIsXG5cdFx0V2luZG93U2hvdzogXCJjb21tb246V2luZG93U2hvd1wiLFxuXHRcdFdpbmRvd0hpZGU6IFwiY29tbW9uOldpbmRvd0hpZGVcIixcblx0XHRXaW5kb3dEUElDaGFuZ2VkOiBcImNvbW1vbjpXaW5kb3dEUElDaGFuZ2VkXCIsXG5cdFx0V2luZG93RmlsZXNEcm9wcGVkOiBcImNvbW1vbjpXaW5kb3dGaWxlc0Ryb3BwZWRcIixcblx0XHRXaW5kb3dSdW50aW1lUmVhZHk6IFwiY29tbW9uOldpbmRvd1J1bnRpbWVSZWFkeVwiLFxuXHRcdFRoZW1lQ2hhbmdlZDogXCJjb21tb246VGhlbWVDaGFuZ2VkXCIsXG5cdH0sXG59O1xuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcGVuRmlsZURpYWxvZ09wdGlvbnNcclxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ2hvb3NlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjaG9zZW4uXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZUZpbGVzXSAtIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DcmVhdGVEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNyZWF0ZWQuXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1Nob3dIaWRkZW5GaWxlc10gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGZpbGVzIHNob3VsZCBiZSBzaG93bi5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbUmVzb2x2ZXNBbGlhc2VzXSAtIEluZGljYXRlcyBpZiBhbGlhc2VzIHNob3VsZCBiZSByZXNvbHZlZC5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbQWxsb3dzTXVsdGlwbGVTZWxlY3Rpb25dIC0gSW5kaWNhdGVzIGlmIG11bHRpcGxlIHNlbGVjdGlvbiBpcyBhbGxvd2VkLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtIaWRlRXh0ZW5zaW9uXSAtIEluZGljYXRlcyBpZiB0aGUgZXh0ZW5zaW9uIHNob3VsZCBiZSBoaWRkZW4uXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhblNlbGVjdEhpZGRlbkV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGV4dGVuc2lvbnMgY2FuIGJlIHNlbGVjdGVkLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtUcmVhdHNGaWxlUGFja2FnZXNBc0RpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBmaWxlIHBhY2thZ2VzIHNob3VsZCBiZSB0cmVhdGVkIGFzIGRpcmVjdG9yaWVzLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtBbGxvd3NPdGhlckZpbGV0eXBlc10gLSBJbmRpY2F0ZXMgaWYgb3RoZXIgZmlsZSB0eXBlcyBhcmUgYWxsb3dlZC5cclxuICogQHByb3BlcnR5IHtGaWxlRmlsdGVyW119IFtGaWx0ZXJzXSAtIEFycmF5IG9mIGZpbGUgZmlsdGVycy5cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtUaXRsZV0gLSBUaXRsZSBvZiB0aGUgZGlhbG9nLlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW01lc3NhZ2VdIC0gTWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbQnV0dG9uVGV4dF0gLSBUZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi5cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtEaXJlY3RvcnldIC0gRGlyZWN0b3J5IHRvIG9wZW4gaW4gdGhlIGRpYWxvZy5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbRGV0YWNoZWRdIC0gSW5kaWNhdGVzIGlmIHRoZSBkaWFsb2cgc2hvdWxkIGFwcGVhciBkZXRhY2hlZCBmcm9tIHRoZSBtYWluIHdpbmRvdy5cclxuICovXHJcblxyXG5cclxuLyoqXHJcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNhdmVGaWxlRGlhbG9nT3B0aW9uc1xyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0ZpbGVuYW1lXSAtIERlZmF1bHQgZmlsZW5hbWUgdG8gdXNlIGluIHRoZSBkaWFsb2cuXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZURpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBkaXJlY3RvcmllcyBjYW4gYmUgY2hvc2VuLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DaG9vc2VGaWxlc10gLSBJbmRpY2F0ZXMgaWYgZmlsZXMgY2FuIGJlIGNob3Nlbi5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ3JlYXRlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtTaG93SGlkZGVuRmlsZXNdIC0gSW5kaWNhdGVzIGlmIGhpZGRlbiBmaWxlcyBzaG91bGQgYmUgc2hvd24uXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1Jlc29sdmVzQWxpYXNlc10gLSBJbmRpY2F0ZXMgaWYgYWxpYXNlcyBzaG91bGQgYmUgcmVzb2x2ZWQuXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c011bHRpcGxlU2VsZWN0aW9uXSAtIEluZGljYXRlcyBpZiBtdWx0aXBsZSBzZWxlY3Rpb24gaXMgYWxsb3dlZC5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbSGlkZUV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgdGhlIGV4dGVuc2lvbiBzaG91bGQgYmUgaGlkZGVuLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5TZWxlY3RIaWRkZW5FeHRlbnNpb25dIC0gSW5kaWNhdGVzIGlmIGhpZGRlbiBleHRlbnNpb25zIGNhbiBiZSBzZWxlY3RlZC5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZmlsZSBwYWNrYWdlcyBzaG91bGQgYmUgdHJlYXRlZCBhcyBkaXJlY3Rvcmllcy5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbQWxsb3dzT3RoZXJGaWxldHlwZXNdIC0gSW5kaWNhdGVzIGlmIG90aGVyIGZpbGUgdHlwZXMgYXJlIGFsbG93ZWQuXHJcbiAqIEBwcm9wZXJ0eSB7RmlsZUZpbHRlcltdfSBbRmlsdGVyc10gLSBBcnJheSBvZiBmaWxlIGZpbHRlcnMuXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGl0bGUgb2YgdGhlIGRpYWxvZy5cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtNZXNzYWdlXSAtIE1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0J1dHRvblRleHRdIC0gVGV4dCB0byBkaXNwbGF5IG9uIHRoZSBidXR0b24uXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRGlyZWN0b3J5XSAtIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0RldGFjaGVkXSAtIEluZGljYXRlcyBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cuXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE1lc3NhZ2VEaWFsb2dPcHRpb25zXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGhlIHRpdGxlIG9mIHRoZSBkaWFsb2cgd2luZG93LlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW01lc3NhZ2VdIC0gVGhlIG1haW4gbWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuXHJcbiAqIEBwcm9wZXJ0eSB7QnV0dG9uW119IFtCdXR0b25zXSAtIEFycmF5IG9mIGJ1dHRvbiBvcHRpb25zIHRvIHNob3cgaW4gdGhlIGRpYWxvZy5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbRGV0YWNoZWRdIC0gVHJ1ZSBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cgKGlmIGFwcGxpY2FibGUpLlxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBCdXR0b25cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtMYWJlbF0gLSBUZXh0IHRoYXQgYXBwZWFycyB3aXRoaW4gdGhlIGJ1dHRvbi5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbSXNDYW5jZWxdIC0gVHJ1ZSBpZiB0aGUgYnV0dG9uIHNob3VsZCBjYW5jZWwgYW4gb3BlcmF0aW9uIHdoZW4gY2xpY2tlZC5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbSXNEZWZhdWx0XSAtIFRydWUgaWYgdGhlIGJ1dHRvbiBzaG91bGQgYmUgdGhlIGRlZmF1bHQgYWN0aW9uIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyBlbnRlci5cclxuICovXHJcblxyXG4vKipcclxuICogQHR5cGVkZWYge09iamVjdH0gRmlsZUZpbHRlclxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0Rpc3BsYXlOYW1lXSAtIERpc3BsYXkgbmFtZSBmb3IgdGhlIGZpbHRlciwgaXQgY291bGQgYmUgXCJUZXh0IEZpbGVzXCIsIFwiSW1hZ2VzXCIgZXRjLlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW1BhdHRlcm5dIC0gUGF0dGVybiB0byBtYXRjaCBmb3IgdGhlIGZpbHRlciwgZS5nLiBcIioudHh0OyoubWRcIiBmb3IgdGV4dCBtYXJrZG93biBmaWxlcy5cclxuICovXHJcblxyXG4vLyBzZXR1cFxyXG53aW5kb3cuX3dhaWxzID0gd2luZG93Ll93YWlscyB8fCB7fTtcclxud2luZG93Ll93YWlscy5kaWFsb2dFcnJvckNhbGxiYWNrID0gZGlhbG9nRXJyb3JDYWxsYmFjaztcclxud2luZG93Ll93YWlscy5kaWFsb2dSZXN1bHRDYWxsYmFjayA9IGRpYWxvZ1Jlc3VsdENhbGxiYWNrO1xyXG5cclxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xyXG5cclxuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSAnbmFub2lkL25vbi1zZWN1cmUnO1xyXG5cclxuLy8gRGVmaW5lIGNvbnN0YW50cyBmcm9tIHRoZSBgbWV0aG9kc2Agb2JqZWN0IGluIFRpdGxlIENhc2VcclxuY29uc3QgRGlhbG9nSW5mbyA9IDA7XHJcbmNvbnN0IERpYWxvZ1dhcm5pbmcgPSAxO1xyXG5jb25zdCBEaWFsb2dFcnJvciA9IDI7XHJcbmNvbnN0IERpYWxvZ1F1ZXN0aW9uID0gMztcclxuY29uc3QgRGlhbG9nT3BlbkZpbGUgPSA0O1xyXG5jb25zdCBEaWFsb2dTYXZlRmlsZSA9IDU7XHJcblxyXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5EaWFsb2csICcnKTtcclxuY29uc3QgZGlhbG9nUmVzcG9uc2VzID0gbmV3IE1hcCgpO1xyXG5cclxuLyoqXHJcbiAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBpZCB0aGF0IGlzIG5vdCBwcmVzZW50IGluIGRpYWxvZ1Jlc3BvbnNlcy5cclxuICogQHJldHVybnMge3N0cmluZ30gdW5pcXVlIGlkXHJcbiAqL1xyXG5mdW5jdGlvbiBnZW5lcmF0ZUlEKCkge1xyXG4gICAgbGV0IHJlc3VsdDtcclxuICAgIGRvIHtcclxuICAgICAgICByZXN1bHQgPSBuYW5vaWQoKTtcclxuICAgIH0gd2hpbGUgKGRpYWxvZ1Jlc3BvbnNlcy5oYXMocmVzdWx0KSk7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG4vKipcclxuICogU2hvd3MgYSBkaWFsb2cgb2Ygc3BlY2lmaWVkIHR5cGUgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHR5cGUgLSB0eXBlIG9mIGRpYWxvZ1xyXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfE9wZW5GaWxlRGlhbG9nT3B0aW9uc3xTYXZlRmlsZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBvcHRpb25zIGZvciB0aGUgZGlhbG9nXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlfSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCByZXN1bHQgb2YgZGlhbG9nXHJcbiAqL1xyXG5mdW5jdGlvbiBkaWFsb2codHlwZSwgb3B0aW9ucyA9IHt9KSB7XHJcbiAgICBjb25zdCBpZCA9IGdlbmVyYXRlSUQoKTtcclxuICAgIG9wdGlvbnNbXCJkaWFsb2ctaWRcIl0gPSBpZDtcclxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgZGlhbG9nUmVzcG9uc2VzLnNldChpZCwge3Jlc29sdmUsIHJlamVjdH0pO1xyXG4gICAgICAgIGNhbGwodHlwZSwgb3B0aW9ucykuY2F0Y2goKGVycm9yKSA9PiB7XHJcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XHJcbiAgICAgICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5kZWxldGUoaWQpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBIYW5kbGVzIHRoZSBjYWxsYmFjayBmcm9tIGEgZGlhbG9nLlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBUaGUgSUQgb2YgdGhlIGRpYWxvZyByZXNwb25zZS5cclxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgLSBUaGUgZGF0YSByZWNlaXZlZCBmcm9tIHRoZSBkaWFsb2cuXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNKU09OIC0gRmxhZyBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIGRhdGEgaXMgaW4gSlNPTiBmb3JtYXQuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cclxuICovXHJcbmZ1bmN0aW9uIGRpYWxvZ1Jlc3VsdENhbGxiYWNrKGlkLCBkYXRhLCBpc0pTT04pIHtcclxuICAgIGxldCBwID0gZGlhbG9nUmVzcG9uc2VzLmdldChpZCk7XHJcbiAgICBpZiAocCkge1xyXG4gICAgICAgIGlmIChpc0pTT04pIHtcclxuICAgICAgICAgICAgcC5yZXNvbHZlKEpTT04ucGFyc2UoZGF0YSkpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHAucmVzb2x2ZShkYXRhKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZGlhbG9nUmVzcG9uc2VzLmRlbGV0ZShpZCk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDYWxsYmFjayBmdW5jdGlvbiBmb3IgaGFuZGxpbmcgZXJyb3JzIGluIGRpYWxvZy5cclxuICpcclxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSBkaWFsb2cgcmVzcG9uc2UuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3ZvaWR9XHJcbiAqL1xyXG5mdW5jdGlvbiBkaWFsb2dFcnJvckNhbGxiYWNrKGlkLCBtZXNzYWdlKSB7XHJcbiAgICBsZXQgcCA9IGRpYWxvZ1Jlc3BvbnNlcy5nZXQoaWQpO1xyXG4gICAgaWYgKHApIHtcclxuICAgICAgICBwLnJlamVjdChtZXNzYWdlKTtcclxuICAgICAgICBkaWFsb2dSZXNwb25zZXMuZGVsZXRlKGlkKTtcclxuICAgIH1cclxufVxyXG5cclxuXHJcbi8vIFJlcGxhY2UgYG1ldGhvZHNgIHdpdGggY29uc3RhbnRzIGluIFRpdGxlIENhc2VcclxuXHJcbi8qKlxyXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcclxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gLSBUaGUgbGFiZWwgb2YgdGhlIGJ1dHRvbiBwcmVzc2VkXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgSW5mbyA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nSW5mbywgb3B0aW9ucyk7XHJcblxyXG4vKipcclxuICogQHBhcmFtIHtNZXNzYWdlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gVGhlIGxhYmVsIG9mIHRoZSBidXR0b24gcHJlc3NlZFxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IFdhcm5pbmcgPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ1dhcm5pbmcsIG9wdGlvbnMpO1xyXG5cclxuLyoqXHJcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcclxuICovXHJcbmV4cG9ydCBjb25zdCBFcnJvciA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nRXJyb3IsIG9wdGlvbnMpO1xyXG5cclxuLyoqXHJcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcclxuICovXHJcbmV4cG9ydCBjb25zdCBRdWVzdGlvbiA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nUXVlc3Rpb24sIG9wdGlvbnMpO1xyXG5cclxuLyoqXHJcbiAqIEBwYXJhbSB7T3BlbkZpbGVEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcclxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nW118c3RyaW5nPn0gUmV0dXJucyBzZWxlY3RlZCBmaWxlIG9yIGxpc3Qgb2YgZmlsZXMuIFJldHVybnMgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaXMgc2VsZWN0ZWQuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgT3BlbkZpbGUgPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ09wZW5GaWxlLCBvcHRpb25zKTtcclxuXHJcbi8qKlxyXG4gKiBAcGFyYW0ge1NhdmVGaWxlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IFJldHVybnMgdGhlIHNlbGVjdGVkIGZpbGUuIFJldHVybnMgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaXMgc2VsZWN0ZWQuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgU2F2ZUZpbGUgPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ1NhdmVGaWxlLCBvcHRpb25zKTtcclxuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuaW1wb3J0IHsgbmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXMgfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZC9ub24tc2VjdXJlJztcclxuXHJcbi8vIFNldHVwXHJcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xyXG53aW5kb3cuX3dhaWxzLmNhbGxSZXN1bHRIYW5kbGVyID0gcmVzdWx0SGFuZGxlcjtcclxud2luZG93Ll93YWlscy5jYWxsRXJyb3JIYW5kbGVyID0gZXJyb3JIYW5kbGVyO1xyXG5cclxuXHJcbmNvbnN0IENhbGxCaW5kaW5nID0gMDtcclxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ2FsbCwgJycpO1xyXG5sZXQgY2FsbFJlc3BvbnNlcyA9IG5ldyBNYXAoKTtcclxuXHJcbi8qKlxyXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgSUQgdXNpbmcgdGhlIG5hbm9pZCBsaWJyYXJ5LlxyXG4gKlxyXG4gKiBAcmV0dXJuIHtzdHJpbmd9IC0gQSB1bmlxdWUgSUQgdGhhdCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgY2FsbFJlc3BvbnNlcyBzZXQuXHJcbiAqL1xyXG5mdW5jdGlvbiBnZW5lcmF0ZUlEKCkge1xyXG4gICAgbGV0IHJlc3VsdDtcclxuICAgIGRvIHtcclxuICAgICAgICByZXN1bHQgPSBuYW5vaWQoKTtcclxuICAgIH0gd2hpbGUgKGNhbGxSZXNwb25zZXMuaGFzKHJlc3VsdCkpO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuLyoqXHJcbiAqIEhhbmRsZXMgdGhlIHJlc3VsdCBvZiBhIGNhbGwgcmVxdWVzdC5cclxuICpcclxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSByZXF1ZXN0IHRvIGhhbmRsZSB0aGUgcmVzdWx0IGZvci5cclxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgLSBUaGUgcmVzdWx0IGRhdGEgb2YgdGhlIHJlcXVlc3QuXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNKU09OIC0gSW5kaWNhdGVzIHdoZXRoZXIgdGhlIGRhdGEgaXMgSlNPTiBvciBub3QuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3VuZGVmaW5lZH0gLSBUaGlzIG1ldGhvZCBkb2VzIG5vdCByZXR1cm4gYW55IHZhbHVlLlxyXG4gKi9cclxuZnVuY3Rpb24gcmVzdWx0SGFuZGxlcihpZCwgZGF0YSwgaXNKU09OKSB7XHJcbiAgICBjb25zdCBwcm9taXNlSGFuZGxlciA9IGdldEFuZERlbGV0ZVJlc3BvbnNlKGlkKTtcclxuICAgIGlmIChwcm9taXNlSGFuZGxlcikge1xyXG4gICAgICAgIHByb21pc2VIYW5kbGVyLnJlc29sdmUoaXNKU09OID8gSlNPTi5wYXJzZShkYXRhKSA6IGRhdGEpO1xyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogSGFuZGxlcyB0aGUgZXJyb3IgZnJvbSBhIGNhbGwgcmVxdWVzdC5cclxuICpcclxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSBwcm9taXNlIGhhbmRsZXIuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UgdG8gcmVqZWN0IHRoZSBwcm9taXNlIGhhbmRsZXIgd2l0aC5cclxuICpcclxuICogQHJldHVybiB7dm9pZH1cclxuICovXHJcbmZ1bmN0aW9uIGVycm9ySGFuZGxlcihpZCwgbWVzc2FnZSkge1xyXG4gICAgY29uc3QgcHJvbWlzZUhhbmRsZXIgPSBnZXRBbmREZWxldGVSZXNwb25zZShpZCk7XHJcbiAgICBpZiAocHJvbWlzZUhhbmRsZXIpIHtcclxuICAgICAgICBwcm9taXNlSGFuZGxlci5yZWplY3QobWVzc2FnZSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXRyaWV2ZXMgYW5kIHJlbW92ZXMgdGhlIHJlc3BvbnNlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gSUQgZnJvbSB0aGUgY2FsbFJlc3BvbnNlcyBtYXAuXHJcbiAqXHJcbiAqIEBwYXJhbSB7YW55fSBpZCAtIFRoZSBJRCBvZiB0aGUgcmVzcG9uc2UgdG8gYmUgcmV0cmlldmVkIGFuZCByZW1vdmVkLlxyXG4gKlxyXG4gKiBAcmV0dXJucyB7YW55fSBUaGUgcmVzcG9uc2Ugb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gSUQuXHJcbiAqL1xyXG5mdW5jdGlvbiBnZXRBbmREZWxldGVSZXNwb25zZShpZCkge1xyXG4gICAgY29uc3QgcmVzcG9uc2UgPSBjYWxsUmVzcG9uc2VzLmdldChpZCk7XHJcbiAgICBjYWxsUmVzcG9uc2VzLmRlbGV0ZShpZCk7XHJcbiAgICByZXR1cm4gcmVzcG9uc2U7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFeGVjdXRlcyBhIGNhbGwgdXNpbmcgdGhlIHByb3ZpZGVkIHR5cGUgYW5kIG9wdGlvbnMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gdHlwZSAtIFRoZSB0eXBlIG9mIGNhbGwgdG8gZXhlY3V0ZS5cclxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSAtIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIGNhbGwuXHJcbiAqIEByZXR1cm4ge1Byb21pc2V9IC0gQSBwcm9taXNlIHRoYXQgd2lsbCBiZSByZXNvbHZlZCBvciByZWplY3RlZCBiYXNlZCBvbiB0aGUgcmVzdWx0IG9mIHRoZSBjYWxsLlxyXG4gKi9cclxuZnVuY3Rpb24gY2FsbEJpbmRpbmcodHlwZSwgb3B0aW9ucyA9IHt9KSB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IGlkID0gZ2VuZXJhdGVJRCgpO1xyXG4gICAgICAgIG9wdGlvbnNbXCJjYWxsLWlkXCJdID0gaWQ7XHJcbiAgICAgICAgY2FsbFJlc3BvbnNlcy5zZXQoaWQsIHsgcmVzb2x2ZSwgcmVqZWN0IH0pO1xyXG4gICAgICAgIGNhbGwodHlwZSwgb3B0aW9ucykuY2F0Y2goKGVycm9yKSA9PiB7XHJcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XHJcbiAgICAgICAgICAgIGNhbGxSZXNwb25zZXMuZGVsZXRlKGlkKTtcclxuICAgICAgICB9KTtcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogQ2FsbCBtZXRob2QuXHJcbiAqXHJcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgZm9yIHRoZSBtZXRob2QuXHJcbiAqIEByZXR1cm5zIHtPYmplY3R9IC0gVGhlIHJlc3VsdCBvZiB0aGUgY2FsbC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBDYWxsKG9wdGlvbnMpIHtcclxuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywgb3B0aW9ucyk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFeGVjdXRlcyBhIG1ldGhvZCBieSBuYW1lLlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgaW4gdGhlIGZvcm1hdCAncGFja2FnZS5zdHJ1Y3QubWV0aG9kJy5cclxuICogQHBhcmFtIHsuLi4qfSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXHJcbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgbmFtZSBpcyBub3QgYSBzdHJpbmcgb3IgaXMgbm90IGluIHRoZSBjb3JyZWN0IGZvcm1hdC5cclxuICogQHJldHVybnMgeyp9IFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBleGVjdXRpb24uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gQnlOYW1lKG5hbWUsIC4uLmFyZ3MpIHtcclxuICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gXCJzdHJpbmdcIiB8fCBuYW1lLnNwbGl0KFwiLlwiKS5sZW5ndGggIT09IDMpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYWxsQnlOYW1lIHJlcXVpcmVzIGEgc3RyaW5nIGluIHRoZSBmb3JtYXQgJ3BhY2thZ2Uuc3RydWN0Lm1ldGhvZCdcIik7XHJcbiAgICB9XHJcbiAgICBsZXQgW3BhY2thZ2VOYW1lLCBzdHJ1Y3ROYW1lLCBtZXRob2ROYW1lXSA9IG5hbWUuc3BsaXQoXCIuXCIpO1xyXG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XHJcbiAgICAgICAgcGFja2FnZU5hbWUsXHJcbiAgICAgICAgc3RydWN0TmFtZSxcclxuICAgICAgICBtZXRob2ROYW1lLFxyXG4gICAgICAgIGFyZ3NcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogQ2FsbHMgYSBtZXRob2QgYnkgaXRzIElEIHdpdGggdGhlIHNwZWNpZmllZCBhcmd1bWVudHMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBtZXRob2RJRCAtIFRoZSBJRCBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXHJcbiAqIEBwYXJhbSB7Li4uKn0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxyXG4gKiBAcmV0dXJuIHsqfSAtIFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBjYWxsLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEJ5SUQobWV0aG9kSUQsIC4uLmFyZ3MpIHtcclxuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywge1xyXG4gICAgICAgIG1ldGhvZElELFxyXG4gICAgICAgIGFyZ3NcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogQ2FsbHMgYSBtZXRob2Qgb24gYSBwbHVnaW4uXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBwbHVnaW5OYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHBsdWdpbi5cclxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXHJcbiAqIEBwYXJhbSB7Li4uKn0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxyXG4gKiBAcmV0dXJucyB7Kn0gLSBUaGUgcmVzdWx0IG9mIHRoZSBtZXRob2QgY2FsbC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBQbHVnaW4ocGx1Z2luTmFtZSwgbWV0aG9kTmFtZSwgLi4uYXJncykge1xyXG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XHJcbiAgICAgICAgcGFja2FnZU5hbWU6IFwid2FpbHMtcGx1Z2luc1wiLFxyXG4gICAgICAgIHN0cnVjdE5hbWU6IHBsdWdpbk5hbWUsXHJcbiAgICAgICAgbWV0aG9kTmFtZSxcclxuICAgICAgICBhcmdzXHJcbiAgICB9KTtcclxufVxyXG4iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuaW1wb3J0IHtkZWJ1Z0xvZ30gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZ1wiO1xyXG5cclxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XHJcblxyXG5pbXBvcnQgKiBhcyBBcHBsaWNhdGlvbiBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb25cIjtcclxuaW1wb3J0ICogYXMgQnJvd3NlciBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvYnJvd3NlclwiO1xyXG5pbXBvcnQgKiBhcyBDbGlwYm9hcmQgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZFwiO1xyXG5pbXBvcnQgKiBhcyBGbGFncyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3NcIjtcclxuaW1wb3J0ICogYXMgU2NyZWVucyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvc2NyZWVuc1wiO1xyXG5pbXBvcnQgKiBhcyBTeXN0ZW0gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbVwiO1xyXG5pbXBvcnQgKiBhcyBXaW5kb3cgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dpbmRvd1wiO1xyXG5pbXBvcnQgKiBhcyBXTUwgZnJvbSAnLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvd21sJztcclxuaW1wb3J0ICogYXMgRXZlbnRzIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9ldmVudHNcIjtcclxuaW1wb3J0ICogYXMgRGlhbG9ncyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZGlhbG9nc1wiO1xyXG5pbXBvcnQgKiBhcyBDYWxsIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxsc1wiO1xyXG5pbXBvcnQge2ludm9rZX0gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbVwiO1xyXG5cclxuLyoqKlxyXG4gVGhpcyB0ZWNobmlxdWUgZm9yIHByb3BlciBsb2FkIGRldGVjdGlvbiBpcyB0YWtlbiBmcm9tIEhUTVg6XHJcblxyXG4gQlNEIDItQ2xhdXNlIExpY2Vuc2VcclxuXHJcbiBDb3B5cmlnaHQgKGMpIDIwMjAsIEJpZyBTa3kgU29mdHdhcmVcclxuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcblxyXG4gUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0XHJcbiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcclxuXHJcbiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcclxuIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxyXG5cclxuIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcclxuIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cclxuIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxyXG5cclxuIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiXHJcbiBBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFXHJcbiBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcclxuIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEVcclxuIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMXHJcbiBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUlxyXG4gU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVJcclxuIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksXHJcbiBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRVxyXG4gT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cclxuXHJcbiAqKiovXHJcblxyXG53aW5kb3cuX3dhaWxzLmludm9rZT1pbnZva2U7XHJcblxyXG53aW5kb3cud2FpbHMgPSB3aW5kb3cud2FpbHMgfHwge307XHJcbndpbmRvdy53YWlscy5BcHBsaWNhdGlvbiA9IEFwcGxpY2F0aW9uO1xyXG53aW5kb3cud2FpbHMuQnJvd3NlciA9IEJyb3dzZXI7XHJcbndpbmRvdy53YWlscy5DYWxsID0gQ2FsbDtcclxud2luZG93LndhaWxzLkNsaXBib2FyZCA9IENsaXBib2FyZDtcclxud2luZG93LndhaWxzLkRpYWxvZ3MgPSBEaWFsb2dzO1xyXG53aW5kb3cud2FpbHMuRXZlbnRzID0gRXZlbnRzO1xyXG53aW5kb3cud2FpbHMuRmxhZ3MgPSBGbGFncztcclxud2luZG93LndhaWxzLlNjcmVlbnMgPSBTY3JlZW5zO1xyXG53aW5kb3cud2FpbHMuU3lzdGVtID0gU3lzdGVtO1xyXG53aW5kb3cud2FpbHMuV2luZG93ID0gV2luZG93O1xyXG53aW5kb3cud2FpbHMuV01MID0gV01MO1xyXG5cclxuXHJcbmxldCBpc1JlYWR5ID0gZmFsc2VcclxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGZ1bmN0aW9uKCkge1xyXG4gICAgaXNSZWFkeSA9IHRydWVcclxuICAgIHdpbmRvdy5fd2FpbHMuaW52b2tlKCd3YWlsczpydW50aW1lOnJlYWR5Jyk7XHJcbiAgICBpZihERUJVRykge1xyXG4gICAgICAgIGRlYnVnTG9nKFwiV2FpbHMgUnVudGltZSBMb2FkZWRcIik7XHJcbiAgICB9XHJcbn0pXHJcblxyXG5mdW5jdGlvbiB3aGVuUmVhZHkoZm4pIHtcclxuICAgIGlmIChpc1JlYWR5IHx8IGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdjb21wbGV0ZScpIHtcclxuICAgICAgICBmbigpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZm4pO1xyXG4gICAgfVxyXG59XHJcblxyXG53aGVuUmVhZHkoKCkgPT4ge1xyXG4gICAgV01MLlJlbG9hZCgpO1xyXG59KTtcclxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7QUFLTyxXQUFTLFNBQVMsU0FBUztBQUU5QixZQUFRO0FBQUEsTUFDSixrQkFBa0IsVUFBVTtBQUFBLE1BQzVCO0FBQUEsTUFDQTtBQUFBLElBQ0o7QUFBQSxFQUNKOzs7QUNaQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7OztBQ0FBLE1BQUksY0FDRjtBQVdLLE1BQUksU0FBUyxDQUFDQSxRQUFPLE9BQU87QUFDakMsUUFBSSxLQUFLO0FBQ1QsUUFBSSxJQUFJQTtBQUNSLFdBQU8sS0FBSztBQUNWLFlBQU0sWUFBYSxLQUFLLE9BQU8sSUFBSSxLQUFNLENBQUM7QUFBQSxJQUM1QztBQUNBLFdBQU87QUFBQSxFQUNUOzs7QUNOQSxNQUFNLGFBQWEsT0FBTyxTQUFTLFNBQVM7QUFHckMsTUFBTSxjQUFjO0FBQUEsSUFDdkIsTUFBTTtBQUFBLElBQ04sV0FBVztBQUFBLElBQ1gsYUFBYTtBQUFBLElBQ2IsUUFBUTtBQUFBLElBQ1IsYUFBYTtBQUFBLElBQ2IsUUFBUTtBQUFBLElBQ1IsUUFBUTtBQUFBLElBQ1IsU0FBUztBQUFBLElBQ1QsUUFBUTtBQUFBLElBQ1Is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TUFDaEMscUJBQXFCO0FBQUEsTUFDckIsNkJBQTZCO0FBQUEsTUFDN0IsMEJBQTBCO0FBQUEsTUFDMUIsdUJBQXVCO0FBQUEsTUFDdkIsdUJBQXVCO0FBQUEsTUFDdkIsMkJBQTJCO0FBQUEsTUFDM0IsK0JBQStCO0FBQUEsTUFDL0Isb0JBQW9CO0FBQUEsTUFDcEIscUJBQXFCO0FBQUEsTUFDckIscUJBQXFCO0FBQUEsTUFDckIsc0JBQXNCO0FBQUEsTUFDdEIsZ0NBQWdDO0FBQUEsTUFDaEMsa0NBQWtDO0FBQUEsTUFDbEMsbUNBQW1DO0FBQUEsTUFDbkMsb0NBQW9DO0FBQUEsTUFDcEMsK0JBQStCO0FBQUEsTUFDL0IsNkJBQTZCO0FBQUEsTUFDN0IsdUJBQXVCO0FBQUEsTUFDdkIsaUNBQWlDO0FBQUEsTUFDakMsOEJBQThCO0FBQUEsTUFDOUIsNEJBQTRCO0FBQUEsTUFDNUIsc0NBQXNDO0FBQUEsTUFDdEMsNEJBQTRCO0FBQUEsTUFDNUIsc0JBQXNCO0FBQUEsTUFDdEIsa0NBQWtDO0FBQUEsTUFDbEMsc0JBQXNCO0FBQUEsTUFDdEIsd0JBQXdCO0FBQUEsTUFDeEIsMkJBQTJCO0FBQUEsTUFDM0Isd0JBQXdCO0FBQUEsTUFDeEIsbUJBQW1CO0FBQUEsTUFDbkIsMEJBQTBCO0FBQUEsTUFDMUIsOEJBQThCO0FBQUEsTUFDOUIseUJBQXlCO0FBQUEsTUFDekIsNkJBQTZCO0FBQUEsTUFDN0IsaUJBQWlCO0FBQUEsTUFDakIsZ0JBQWdCO0FBQUEsTUFDaEIsc0JBQXNCO0FBQUEsTUFDdEIsZUFBZTtBQUFBLE1BQ2YseUJBQXlCO0FBQUEsTUFDekIsd0JBQXdCO0FBQUEsTUFDeEIsb0JBQW9CO0FBQUEsTUFDcEIscUJBQXFCO0FBQUEsTUFDckIsaUJBQWlCO0FBQUEsTUFDakIsaUJBQWlCO0FBQUEsTUFDakIsc0JBQXNCO0FBQUEsTUFDdEIsbUNBQW1DO0FBQUEsTUFDbkMscUNBQXFDO0FBQUEsTUFDckMsdUJBQXVCO0FBQUEsTUFDdkIsc0JBQXNCO0FBQUEsTUFDdEIsd0JBQXdCO0FBQUEsTUFDeEIsMkJBQTJCO0FBQUEsTUFDM0IsbUJBQW1CO0FBQUEsTUFDbkIscUJBQXFCO0FBQUEsTUFDckIsc0JBQXNCO0FBQUEsTUFDdEIsc0JBQXNCO0FBQUEsTUFDdEIsOEJBQThCO0FBQUEsTUFDOUIsaUJBQWlCO0FBQUEsTUFDakIseUJBQXlCO0FBQUEsTUFDekIsMkJBQTJCO0FBQUEsTUFDM0IsK0JBQStCO0FBQUEsTUFDL0IsMEJBQTBCO0FBQUEsTUFDMUIsOEJBQThCO0FBQUEsTUFDOUIsaUJBQWlCO0FBQUEsTUFDakIsdUJBQXVCO0FBQUEsTUFDdkIsZ0JBQWdCO0FBQUEsTUFDaEIsMEJBQTBCO0FBQUEsTUFDMUIseUJBQXlCO0FBQUEsTUFDekIsc0JBQXNCO0FBQUEsTUFDdEIsa0JBQWtCO0FBQUEsTUFDbEIsbUJBQW1CO0FBQUEsTUFDbkIsa0JBQWtCO0FBQUEsTUFDbEIsdUJBQXVCO0FBQUEsTUFDdkIsb0NBQW9DO0FBQUEsTUFDcEMsc0NBQXNDO0FBQUEsTUFDdEMsd0JBQXdCO0FBQUEsTUFDeEIsdUJBQXVCO0FBQUEsTUFDdkIseUJBQXlCO0FBQUEsTUFDekIsNEJBQTRCO0FBQUEsTUFDNUIsNEJBQTRCO0FBQUEsTUFDNUIsY0FBYztBQUFBLE1BQ2QsYUFBYTtBQUFBLE1BQ2IsY0FBYztBQUFBLE1BQ2Qsb0JBQW9CO0FBQUEsTUFDcEIsbUJBQW1CO0FBQUEsTUFDbkIsdUJBQXVCO0FBQUEsTUFDdkIsc0JBQXNCO0FBQUEsTUFDdEIscUJBQXFCO0FBQUEsTUFDckIsb0JBQW9CO0FBQUEsTUFDcEIsaUJBQWlCO0FBQUEsTUFDakIsZ0JBQWdCO0FBQUEsTUFDaEIsb0JBQW9CO0FBQUEsTUFDcEIsbUJBQW1CO0FBQUEsTUFDbkIsdUJBQXVCO0FBQUEsTUFDdkIsc0JBQXNCO0FBQUEsTUFDdEIscUJBQXFCO0FBQUEsTUFDckIsb0JBQW9CO0FBQUEsTUFDcEIsZ0JBQWdCO0FBQUEsTUFDaEIsZUFBZTtBQUFBLE1BQ2YsZUFBZTtBQUFBLE1BQ2YsY0FBYztBQUFBLE1BQ2QsMEJBQTBCO0FBQUEsTUFD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TyxZQUFZLGFBQWE7QUFBQSxNQUM1QixhQUFhO0FBQUEsTUFDYixZQUFZO0FBQUEsTUFDWjtBQUFBLE1BQ0E7QUFBQSxJQUNKLENBQUM7QUFBQSxFQUNMOzs7QUNwSkEsU0FBTyxTQUFTLE9BQU8sVUFBVSxDQUFDO0FBOENsQyxTQUFPLE9BQU8sU0FBTztBQUVyQixTQUFPLFFBQVEsT0FBTyxTQUFTLENBQUM7QUFDaEMsU0FBTyxNQUFNLGNBQWM7QUFDM0IsU0FBTyxNQUFNLFVBQVU7QUFDdkIsU0FBTyxNQUFNLE9BQU87QUFDcEIsU0FBTyxNQUFNLFlBQVk7QUFDekIsU0FBTyxNQUFNLFVBQVU7QUFDdkIsU0FBTyxNQUFNLFNBQVM7QUFDdEIsU0FBTyxNQUFNLFFBQVE7QUFDckIsU0FBTyxNQUFNLFVBQVU7QUFDdkIsU0FBTyxNQUFNLFNBQVM7QUFDdEIsU0FBTyxNQUFNLFNBQVM7QUFDdEIsU0FBTyxNQUFNLE1BQU07QUFHbkIsTUFBSSxVQUFVO0FBQ2QsV0FBUyxpQkFBaUIsb0JBQW9CLFdBQVc7QUFDckQsY0FBVTtBQUNWLFdBQU8sT0FBTyxPQUFPLHFCQUFxQjtBQUMxQyxRQUFHLE1BQU87QUFDTixlQUFTLHNCQUFzQjtBQUFBLElBQ25DO0FBQUEsRUFDSixDQUFDO0FBRUQsV0FBUyxVQUFVLElBQUk7QUFDbkIsUUFBSSxXQUFXLFNBQVMsZUFBZSxZQUFZO0FBQy9DLFNBQUc7QUFBQSxJQUNQLE9BQU87QUFDSCxlQUFTLGlCQUFpQixvQkFBb0IsRUFBRTtBQUFBLElBQ3BEO0FBQUEsRUFDSjtBQUVBLFlBQVUsTUFBTTtBQUNaLElBQUksT0FBTztBQUFBLEVBQ2YsQ0FBQzsiLAogICJuYW1lcyI6IFsic2l6ZSIsICJjYWxsIiwgImNhbGwiLCAiY2FsbCIsICJjYWxsIiwgIkhpZGUiLCAiU2hvdyIsICJjYWxsIiwgIndpZHRoIiwgImhlaWdodCIsICJIaWRlIiwgIlNob3ciLCAiY2FsbCIsICJldmVudE5hbWUiLCAiRXJyb3IiLCAiY2FsbCIsICJFcnJvciIsICJjYWxsIiwgImdlbmVyYXRlSUQiXQp9Cg== diff --git a/v3/examples/window-api/assets/runtime.js b/v3/examples/window-api/assets/runtime.js new file mode 100644 index 00000000000..ec430090db6 --- /dev/null +++ b/v3/examples/window-api/assets/runtime.js @@ -0,0 +1 @@ +(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>Me,Text:()=>xe});var q=l(d.Clipboard,""),Ce=0,Se=1;function Me(e){return q(Ce,{text:e})}function xe(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var M=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",M=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(M=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){M=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return M&&i>0?(h("drag"),!1):M}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,Mi=21,xi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(Mi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(xi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>x,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},x=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,Mn=5,xn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),xn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(Mn,e);function oe(e,i=null){let n=new x(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/examples/window-api/main.go b/v3/examples/window-api/main.go new file mode 100644 index 00000000000..391b09dfd48 --- /dev/null +++ b/v3/examples/window-api/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "embed" + "log" + + "github.com/wailsapp/wails/v3/pkg/application" +) + +//go:embed assets/* +var assets embed.FS + +func main() { + + app := application.New(application.Options{ + Name: "JS Window API Demo", + Description: "A demo of the JS Window API", + Mac: application.MacOptions{ + ApplicationShouldTerminateAfterLastWindowClosed: true, + }, + Assets: application.AssetOptions{ + Handler: application.AssetFileServerFS(assets), + }, + }) + + app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + Title: "JS Window API Demo", + Width: 1280, + Height: 1024, + Mac: application.MacWindow{ + Backdrop: application.MacBackdropTranslucent, + TitleBar: application.MacTitleBarHiddenInsetUnified, + InvisibleTitleBarHeight: 50, + }, + }) + + err := app.Run() + + if err != nil { + log.Fatal(err.Error()) + } +} diff --git a/v3/internal/commands/build_assets/runtime/runtime.debug.js b/v3/internal/commands/build_assets/runtime/runtime.debug.js index da541011d74..694da23aeab 100644 --- a/v3/internal/commands/build_assets/runtime/runtime.debug.js +++ b/v3/internal/commands/build_assets/runtime/runtime.debug.js @@ -1112,4 +1112,4 @@ Reload(); }); })(); -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb24uanMiLCAiLi4vLi4vLi4vcnVudGltZS9ub2RlX21vZHVsZXMvbmFub2lkL25vbi1zZWN1cmUvaW5kZXguanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3J1bnRpbWUuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXIuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZC5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvc3lzdGVtLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jb250ZXh0bWVudS5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3MuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RyYWcuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3NjcmVlbnMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dpbmRvdy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvd21sLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9ldmVudHMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50X3R5cGVzLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9kaWFsb2dzLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxscy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvY29tcGlsZWQvbWFpbi5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXHJcbiAqIExvZ3MgYSBtZXNzYWdlIHRvIHRoZSBjb25zb2xlIHdpdGggY3VzdG9tIGZvcm1hdHRpbmcuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIG1lc3NhZ2UgdG8gYmUgbG9nZ2VkLlxyXG4gKiBAcmV0dXJuIHt2b2lkfVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGRlYnVnTG9nKG1lc3NhZ2UpIHtcclxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxyXG4gICAgY29uc29sZS5sb2coXHJcbiAgICAgICAgJyVjIHdhaWxzMyAlYyAnICsgbWVzc2FnZSArICcgJyxcclxuICAgICAgICAnYmFja2dyb3VuZDogI2FhMDAwMDsgY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDNweCAwcHggMHB4IDNweDsgcGFkZGluZzogMXB4OyBmb250LXNpemU6IDAuN3JlbScsXHJcbiAgICAgICAgJ2JhY2tncm91bmQ6ICMwMDk5MDA7IGNvbG9yOiAjZmZmOyBib3JkZXItcmFkaXVzOiAwcHggM3B4IDNweCAwcHg7IHBhZGRpbmc6IDFweDsgZm9udC1zaXplOiAwLjdyZW0nXHJcbiAgICApO1xyXG59IiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZVwiO1xyXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5BcHBsaWNhdGlvbiwgJycpO1xyXG5cclxuY29uc3QgSGlkZU1ldGhvZCA9IDA7XHJcbmNvbnN0IFNob3dNZXRob2QgPSAxO1xyXG5jb25zdCBRdWl0TWV0aG9kID0gMjtcclxuXHJcbi8qKlxyXG4gKiBIaWRlcyBhIGNlcnRhaW4gbWV0aG9kIGJ5IGNhbGxpbmcgdGhlIEhpZGVNZXRob2QgZnVuY3Rpb24uXHJcbiAqXHJcbiAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XHJcbiAqXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gSGlkZSgpIHtcclxuICAgIHJldHVybiBjYWxsKEhpZGVNZXRob2QpO1xyXG59XHJcblxyXG4vKipcclxuICogQ2FsbHMgdGhlIFNob3dNZXRob2QgYW5kIHJldHVybnMgdGhlIHJlc3VsdC5cclxuICpcclxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTaG93KCkge1xyXG4gICAgcmV0dXJuIGNhbGwoU2hvd01ldGhvZCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDYWxscyB0aGUgUXVpdE1ldGhvZCB0byB0ZXJtaW5hdGUgdGhlIHByb2dyYW0uXHJcbiAqXHJcbiAqIEByZXR1cm4ge1Byb21pc2U8dm9pZD59XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gUXVpdCgpIHtcclxuICAgIHJldHVybiBjYWxsKFF1aXRNZXRob2QpO1xyXG59XHJcbiIsICJsZXQgdXJsQWxwaGFiZXQgPVxuICAndXNlYW5kb20tMjZUMTk4MzQwUFg3NXB4SkFDS1ZFUllNSU5EQlVTSFdPTEZfR1FaYmZnaGprbHF2d3l6cmljdCdcbmV4cG9ydCBsZXQgY3VzdG9tQWxwaGFiZXQgPSAoYWxwaGFiZXQsIGRlZmF1bHRTaXplID0gMjEpID0+IHtcbiAgcmV0dXJuIChzaXplID0gZGVmYXVsdFNpemUpID0+IHtcbiAgICBsZXQgaWQgPSAnJ1xuICAgIGxldCBpID0gc2l6ZVxuICAgIHdoaWxlIChpLS0pIHtcbiAgICAgIGlkICs9IGFscGhhYmV0WyhNYXRoLnJhbmRvbSgpICogYWxwaGFiZXQubGVuZ3RoKSB8IDBdXG4gICAgfVxuICAgIHJldHVybiBpZFxuICB9XG59XG5leHBvcnQgbGV0IG5hbm9pZCA9IChzaXplID0gMjEpID0+IHtcbiAgbGV0IGlkID0gJydcbiAgbGV0IGkgPSBzaXplXG4gIHdoaWxlIChpLS0pIHtcbiAgICBpZCArPSB1cmxBbHBoYWJldFsoTWF0aC5yYW5kb20oKSAqIDY0KSB8IDBdXG4gIH1cbiAgcmV0dXJuIGlkXG59XG4iLCAiLypcclxuIF8gICAgIF9fICAgICBfIF9fXHJcbnwgfCAgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5pbXBvcnQgeyBuYW5vaWQgfSBmcm9tICduYW5vaWQvbm9uLXNlY3VyZSc7XHJcblxyXG5jb25zdCBydW50aW1lVVJMID0gd2luZG93LmxvY2F0aW9uLm9yaWdpbiArIFwiL3dhaWxzL3J1bnRpbWVcIjtcclxuXHJcbi8vIE9iamVjdCBOYW1lc1xyXG5leHBvcnQgY29uc3Qgb2JqZWN0TmFtZXMgPSB7XHJcbiAgICBDYWxsOiAwLFxyXG4gICAgQ2xpcGJvYXJkOiAxLFxyXG4gICAgQXBwbGljYXRpb246IDIsXHJcbiAgICBFdmVudHM6IDMsXHJcbiAgICBDb250ZXh0TWVudTogNCxcclxuICAgIERpYWxvZzogNSxcclxuICAgIFdpbmRvdzogNixcclxuICAgIFNjcmVlbnM6IDcsXHJcbiAgICBTeXN0ZW06IDgsXHJcbiAgICBCcm93c2VyOiA5LFxyXG59XHJcbmV4cG9ydCBsZXQgY2xpZW50SWQgPSBuYW5vaWQoKTtcclxuXHJcbi8qKlxyXG4gKiBDcmVhdGVzIGEgcnVudGltZSBjYWxsZXIgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGEgc3BlY2lmaWVkIG1ldGhvZCBvbiBhIGdpdmVuIG9iamVjdCB3aXRoaW4gYSBzcGVjaWZpZWQgd2luZG93IGNvbnRleHQuXHJcbiAqXHJcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgLSBUaGUgb2JqZWN0IG9uIHdoaWNoIHRoZSBtZXRob2QgaXMgdG8gYmUgaW52b2tlZC5cclxuICogQHBhcmFtIHtzdHJpbmd9IHdpbmRvd05hbWUgLSBUaGUgbmFtZSBvZiB0aGUgd2luZG93IGNvbnRleHQgaW4gd2hpY2ggdGhlIG1ldGhvZCBzaG91bGQgYmUgY2FsbGVkLlxyXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IEEgcnVudGltZSBjYWxsZXIgZnVuY3Rpb24gdGhhdCB0YWtlcyB0aGUgbWV0aG9kIG5hbWUgYW5kIG9wdGlvbmFsbHkgYXJndW1lbnRzIGFuZCBpbnZva2VzIHRoZSBtZXRob2Qgd2l0aGluIHRoZSBzcGVjaWZpZWQgd2luZG93IGNvbnRleHQuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gbmV3UnVudGltZUNhbGxlcihvYmplY3QsIHdpbmRvd05hbWUpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAobWV0aG9kLCBhcmdzPW51bGwpIHtcclxuICAgICAgICByZXR1cm4gcnVudGltZUNhbGwob2JqZWN0ICsgXCIuXCIgKyBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpO1xyXG4gICAgfTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENyZWF0ZXMgYSBuZXcgcnVudGltZSBjYWxsZXIgd2l0aCBzcGVjaWZpZWQgSUQuXHJcbiAqXHJcbiAqIEBwYXJhbSB7b2JqZWN0fSBvYmplY3QgLSBUaGUgb2JqZWN0IHRvIGludm9rZSB0aGUgbWV0aG9kIG9uLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cuXHJcbiAqIEByZXR1cm4ge0Z1bmN0aW9ufSAtIFRoZSBuZXcgcnVudGltZSBjYWxsZXIgZnVuY3Rpb24uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3QsIHdpbmRvd05hbWUpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAobWV0aG9kLCBhcmdzPW51bGwpIHtcclxuICAgICAgICByZXR1cm4gcnVudGltZUNhbGxXaXRoSUQob2JqZWN0LCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpO1xyXG4gICAgfTtcclxufVxyXG5cclxuXHJcbmZ1bmN0aW9uIHJ1bnRpbWVDYWxsKG1ldGhvZCwgd2luZG93TmFtZSwgYXJncykge1xyXG4gICAgbGV0IHVybCA9IG5ldyBVUkwocnVudGltZVVSTCk7XHJcbiAgICBpZiggbWV0aG9kICkge1xyXG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwibWV0aG9kXCIsIG1ldGhvZCk7XHJcbiAgICB9XHJcbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xyXG4gICAgICAgIGhlYWRlcnM6IHt9LFxyXG4gICAgfTtcclxuICAgIGlmICh3aW5kb3dOYW1lKSB7XHJcbiAgICAgICAgZmV0Y2hPcHRpb25zLmhlYWRlcnNbXCJ4LXdhaWxzLXdpbmRvdy1uYW1lXCJdID0gd2luZG93TmFtZTtcclxuICAgIH1cclxuICAgIGlmIChhcmdzKSB7XHJcbiAgICAgICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJhcmdzXCIsIEpTT04uc3RyaW5naWZ5KGFyZ3MpKTtcclxuICAgIH1cclxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcclxuXHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICAgIGZldGNoKHVybCwgZmV0Y2hPcHRpb25zKVxyXG4gICAgICAgICAgICAudGhlbihyZXNwb25zZSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2Uub2spIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayBjb250ZW50IHR5cGVcclxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UuaGVhZGVycy5nZXQoXCJDb250ZW50LVR5cGVcIikgJiYgcmVzcG9uc2UuaGVhZGVycy5nZXQoXCJDb250ZW50LVR5cGVcIikuaW5kZXhPZihcImFwcGxpY2F0aW9uL2pzb25cIikgIT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLnRleHQoKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IocmVzcG9uc2Uuc3RhdHVzVGV4dCkpO1xyXG4gICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAudGhlbihkYXRhID0+IHJlc29sdmUoZGF0YSkpXHJcbiAgICAgICAgICAgIC5jYXRjaChlcnJvciA9PiByZWplY3QoZXJyb3IpKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBydW50aW1lQ2FsbFdpdGhJRChvYmplY3RJRCwgbWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKSB7XHJcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcclxuICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwib2JqZWN0XCIsIG9iamVjdElEKTtcclxuICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwibWV0aG9kXCIsIG1ldGhvZCk7XHJcbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xyXG4gICAgICAgIGhlYWRlcnM6IHt9LFxyXG4gICAgfTtcclxuICAgIGlmICh3aW5kb3dOYW1lKSB7XHJcbiAgICAgICAgZmV0Y2hPcHRpb25zLmhlYWRlcnNbXCJ4LXdhaWxzLXdpbmRvdy1uYW1lXCJdID0gd2luZG93TmFtZTtcclxuICAgIH1cclxuICAgIGlmIChhcmdzKSB7XHJcbiAgICAgICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJhcmdzXCIsIEpTT04uc3RyaW5naWZ5KGFyZ3MpKTtcclxuICAgIH1cclxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcclxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgZmV0Y2godXJsLCBmZXRjaE9wdGlvbnMpXHJcbiAgICAgICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcclxuICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5vaykge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGNvbnRlbnQgdHlwZVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKSAmJiByZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKS5pbmRleE9mKFwiYXBwbGljYXRpb24vanNvblwiKSAhPT0gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcihyZXNwb25zZS5zdGF0dXNUZXh0KSk7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIC50aGVuKGRhdGEgPT4gcmVzb2x2ZShkYXRhKSlcclxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xyXG4gICAgfSk7XHJcbn1cclxuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xyXG5cclxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQnJvd3NlciwgJycpO1xyXG5jb25zdCBCcm93c2VyT3BlblVSTCA9IDA7XHJcblxyXG4vKipcclxuICogT3BlbiBhIGJyb3dzZXIgd2luZG93IHRvIHRoZSBnaXZlbiBVUkxcclxuICogQHBhcmFtIHtzdHJpbmd9IHVybCAtIFRoZSBVUkwgdG8gb3BlblxyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIE9wZW5VUkwodXJsKSB7XHJcbiAgICByZXR1cm4gY2FsbChCcm93c2VyT3BlblVSTCwge3VybH0pO1xyXG59XHJcbiIsICIvKlxyXG4gX1x0ICAgX19cdCAgXyBfX1xyXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXHJcblxyXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcblxyXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5DbGlwYm9hcmQsICcnKTtcclxuY29uc3QgQ2xpcGJvYXJkU2V0VGV4dCA9IDA7XHJcbmNvbnN0IENsaXBib2FyZFRleHQgPSAxO1xyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIHRleHQgdG8gdGhlIENsaXBib2FyZC5cclxuICpcclxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgdGV4dCB0byBiZSBzZXQgdG8gdGhlIENsaXBib2FyZC5cclxuICogQHJldHVybiB7UHJvbWlzZX0gLSBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBvcGVyYXRpb24gaXMgc3VjY2Vzc2Z1bC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTZXRUZXh0KHRleHQpIHtcclxuICAgIHJldHVybiBjYWxsKENsaXBib2FyZFNldFRleHQsIHt0ZXh0fSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZXQgdGhlIENsaXBib2FyZCB0ZXh0XHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHRleHQgZnJvbSB0aGUgQ2xpcGJvYXJkLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFRleHQoKSB7XHJcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRUZXh0KTtcclxufVxyXG4iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5cclxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xyXG5sZXQgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU3lzdGVtLCAnJyk7XHJcbmNvbnN0IHN5c3RlbUlzRGFya01vZGUgPSAwO1xyXG5jb25zdCBlbnZpcm9ubWVudCA9IDE7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gaW52b2tlKG1zZykge1xyXG4gICAgaWYod2luZG93LmNocm9tZSkge1xyXG4gICAgICAgIHJldHVybiB3aW5kb3cuY2hyb21lLndlYnZpZXcucG9zdE1lc3NhZ2UobXNnKTtcclxuICAgIH1cclxuICAgIHJldHVybiB3aW5kb3cud2Via2l0Lm1lc3NhZ2VIYW5kbGVycy5leHRlcm5hbC5wb3N0TWVzc2FnZShtc2cpO1xyXG59XHJcblxyXG4vKipcclxuICogQGZ1bmN0aW9uXHJcbiAqIFJldHJpZXZlcyB0aGUgc3lzdGVtIGRhcmsgbW9kZSBzdGF0dXMuXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fSAtIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGEgYm9vbGVhbiB2YWx1ZSBpbmRpY2F0aW5nIGlmIHRoZSBzeXN0ZW0gaXMgaW4gZGFyayBtb2RlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIElzRGFya01vZGUoKSB7XHJcbiAgICByZXR1cm4gY2FsbChzeXN0ZW1Jc0RhcmtNb2RlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEZldGNoZXMgdGhlIGNhcGFiaWxpdGllcyBvZiB0aGUgYXBwbGljYXRpb24gZnJvbSB0aGUgc2VydmVyLlxyXG4gKlxyXG4gKiBAYXN5bmNcclxuICogQGZ1bmN0aW9uIENhcGFiaWxpdGllc1xyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxPYmplY3Q+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgY2FwYWJpbGl0aWVzLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIENhcGFiaWxpdGllcygpIHtcclxuICAgIGxldCByZXNwb25zZSA9IGZldGNoKFwiL3dhaWxzL2NhcGFiaWxpdGllc1wiKTtcclxuICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBFbnZpcm9ubWVudEluZm9cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IE9TIC0gVGhlIG9wZXJhdGluZyBzeXN0ZW0gaW4gdXNlLlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQXJjaCAtIFRoZSBhcmNoaXRlY3R1cmUgb2YgdGhlIHN5c3RlbS5cclxuICovXHJcblxyXG4vKipcclxuICogQGZ1bmN0aW9uXHJcbiAqIFJldHJpZXZlcyBlbnZpcm9ubWVudCBkZXRhaWxzLlxyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxFbnZpcm9ubWVudEluZm8+fSAtIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIG9iamVjdCBjb250YWluaW5nIE9TIGFuZCBzeXN0ZW0gYXJjaGl0ZWN0dXJlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEVudmlyb25tZW50KCkge1xyXG4gICAgcmV0dXJuIGNhbGwoZW52aXJvbm1lbnQpO1xyXG59XHJcblxyXG4vKipcclxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cy5cclxuICpcclxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgb3BlcmF0aW5nIHN5c3RlbSBpcyBXaW5kb3dzLCBvdGhlcndpc2UgZmFsc2UuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gSXNXaW5kb3dzKCkge1xyXG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuT1MgPT09IFwid2luZG93c1wiO1xyXG59XHJcblxyXG4vKipcclxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgTGludXguXHJcbiAqXHJcbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIHRydWUgaWYgdGhlIGN1cnJlbnQgb3BlcmF0aW5nIHN5c3RlbSBpcyBMaW51eCwgZmFsc2Ugb3RoZXJ3aXNlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIElzTGludXgoKSB7XHJcbiAgICByZXR1cm4gd2luZG93Ll93YWlscy5lbnZpcm9ubWVudC5PUyA9PT0gXCJsaW51eFwiO1xyXG59XHJcblxyXG4vKipcclxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGlzIGEgbWFjT1Mgb3BlcmF0aW5nIHN5c3RlbS5cclxuICpcclxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIGVudmlyb25tZW50IGlzIG1hY09TLCBmYWxzZSBvdGhlcndpc2UuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gSXNNYWMoKSB7XHJcbiAgICByZXR1cm4gd2luZG93Ll93YWlscy5lbnZpcm9ubWVudC5PUyA9PT0gXCJkYXJ3aW5cIjtcclxufVxyXG5cclxuLyoqXHJcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQuXHJcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGFyY2hpdGVjdHVyZSBpcyBBTUQ2NCwgZmFsc2Ugb3RoZXJ3aXNlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIElzQU1ENjQoKSB7XHJcbiAgICByZXR1cm4gd2luZG93Ll93YWlscy5lbnZpcm9ubWVudC5BcmNoID09PSBcImFtZDY0XCI7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgYXJjaGl0ZWN0dXJlIGlzIEFSTS5cclxuICpcclxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIGN1cnJlbnQgYXJjaGl0ZWN0dXJlIGlzIEFSTSwgZmFsc2Ugb3RoZXJ3aXNlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIElzQVJNKCkge1xyXG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuQXJjaCA9PT0gXCJhcm1cIjtcclxufVxyXG5cclxuLyoqXHJcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBpcyBBUk02NCBhcmNoaXRlY3R1cmUuXHJcbiAqXHJcbiAqIEByZXR1cm5zIHtib29sZWFufSAtIFJldHVybnMgdHJ1ZSBpZiB0aGUgZW52aXJvbm1lbnQgaXMgQVJNNjQgYXJjaGl0ZWN0dXJlLCBvdGhlcndpc2UgcmV0dXJucyBmYWxzZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBJc0FSTTY0KCkge1xyXG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuQXJjaCA9PT0gXCJhcm02NFwiO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gSXNEZWJ1ZygpIHtcclxuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkRlYnVnID09PSB0cnVlO1xyXG59XHJcblxyXG4iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5cclxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xyXG5pbXBvcnQge0lzRGVidWd9IGZyb20gXCIuL3N5c3RlbVwiO1xyXG5cclxuLy8gc2V0dXBcclxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgY29udGV4dE1lbnVIYW5kbGVyKTtcclxuXHJcbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkNvbnRleHRNZW51LCAnJyk7XHJcbmNvbnN0IENvbnRleHRNZW51T3BlbiA9IDA7XHJcblxyXG5mdW5jdGlvbiBvcGVuQ29udGV4dE1lbnUoaWQsIHgsIHksIGRhdGEpIHtcclxuICAgIHZvaWQgY2FsbChDb250ZXh0TWVudU9wZW4sIHtpZCwgeCwgeSwgZGF0YX0pO1xyXG59XHJcblxyXG5mdW5jdGlvbiBjb250ZXh0TWVudUhhbmRsZXIoZXZlbnQpIHtcclxuICAgIC8vIENoZWNrIGZvciBjdXN0b20gY29udGV4dCBtZW51XHJcbiAgICBsZXQgZWxlbWVudCA9IGV2ZW50LnRhcmdldDtcclxuICAgIGxldCBjdXN0b21Db250ZXh0TWVudSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoXCItLWN1c3RvbS1jb250ZXh0bWVudVwiKTtcclxuICAgIGN1c3RvbUNvbnRleHRNZW51ID0gY3VzdG9tQ29udGV4dE1lbnUgPyBjdXN0b21Db250ZXh0TWVudS50cmltKCkgOiBcIlwiO1xyXG4gICAgaWYgKGN1c3RvbUNvbnRleHRNZW51KSB7XHJcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBsZXQgY3VzdG9tQ29udGV4dE1lbnVEYXRhID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCkuZ2V0UHJvcGVydHlWYWx1ZShcIi0tY3VzdG9tLWNvbnRleHRtZW51LWRhdGFcIik7XHJcbiAgICAgICAgb3BlbkNvbnRleHRNZW51KGN1c3RvbUNvbnRleHRNZW51LCBldmVudC5jbGllbnRYLCBldmVudC5jbGllbnRZLCBjdXN0b21Db250ZXh0TWVudURhdGEpO1xyXG4gICAgICAgIHJldHVyblxyXG4gICAgfVxyXG5cclxuICAgIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpO1xyXG59XHJcblxyXG5cclxuLypcclxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBhdXRvOyAoZGVmYXVsdCkgd2lsbCBzaG93IHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudSBpZiBjb250ZW50RWRpdGFibGUgaXMgdHJ1ZSBPUiB0ZXh0IGhhcyBiZWVuIHNlbGVjdGVkIE9SIGVsZW1lbnQgaXMgaW5wdXQgb3IgdGV4dGFyZWFcclxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBzaG93OyB3aWxsIGFsd2F5cyBzaG93IHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxyXG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IGhpZGU7IHdpbGwgYWx3YXlzIGhpZGUgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51XHJcblxyXG5UaGlzIHJ1bGUgaXMgaW5oZXJpdGVkIGxpa2Ugbm9ybWFsIENTUyBydWxlcywgc28gbmVzdGluZyB3b3JrcyBhcyBleHBlY3RlZFxyXG4qL1xyXG5mdW5jdGlvbiBwcm9jZXNzRGVmYXVsdENvbnRleHRNZW51KGV2ZW50KSB7XHJcblxyXG4gICAgLy8gRGVidWcgYnVpbGRzIGFsd2F5cyBzaG93IHRoZSBtZW51XHJcbiAgICBpZiAoSXNEZWJ1ZygpKSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFByb2Nlc3MgZGVmYXVsdCBjb250ZXh0IG1lbnVcclxuICAgIGNvbnN0IGVsZW1lbnQgPSBldmVudC50YXJnZXQ7XHJcbiAgICBjb25zdCBjb21wdXRlZFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XHJcbiAgICBjb25zdCBkZWZhdWx0Q29udGV4dE1lbnVBY3Rpb24gPSBjb21wdXRlZFN0eWxlLmdldFByb3BlcnR5VmFsdWUoXCItLWRlZmF1bHQtY29udGV4dG1lbnVcIikudHJpbSgpO1xyXG4gICAgc3dpdGNoIChkZWZhdWx0Q29udGV4dE1lbnVBY3Rpb24pIHtcclxuICAgICAgICBjYXNlIFwic2hvd1wiOlxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgY2FzZSBcImhpZGVcIjpcclxuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlXHJcbiAgICAgICAgICAgIGlmIChlbGVtZW50LmlzQ29udGVudEVkaXRhYmxlKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRleHQgaGFzIGJlZW4gc2VsZWN0ZWRcclxuICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xyXG4gICAgICAgICAgICBjb25zdCBoYXNTZWxlY3Rpb24gPSAoc2VsZWN0aW9uLnRvU3RyaW5nKCkubGVuZ3RoID4gMClcclxuICAgICAgICAgICAgaWYgKGhhc1NlbGVjdGlvbikge1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3Rpb24ucmFuZ2VDb3VudDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdChpKTtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0cyA9IHJhbmdlLmdldENsaWVudFJlY3RzKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCByZWN0cy5sZW5ndGg7IGorKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0ID0gcmVjdHNbal07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KHJlY3QubGVmdCwgcmVjdC50b3ApID09PSBlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGFnbmFtZSBpcyBpbnB1dCBvciB0ZXh0YXJlYVxyXG4gICAgICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lID09PSBcIklOUFVUXCIgfHwgZWxlbWVudC50YWdOYW1lID09PSBcIlRFWFRBUkVBXCIpIHtcclxuICAgICAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24gfHwgKCFlbGVtZW50LnJlYWRPbmx5ICYmICFlbGVtZW50LmRpc2FibGVkKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gaGlkZSBkZWZhdWx0IGNvbnRleHQgbWVudVxyXG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgfVxyXG59XHJcbiIsICIvKlxyXG4gX1x0ICAgX19cdCAgXyBfX1xyXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXHJcblxyXG4vKipcclxuICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBrZXkgZnJvbSB0aGUgZmxhZyBtYXAuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXlTdHJpbmcgLSBUaGUga2V5IHRvIHJldHJpZXZlIHRoZSB2YWx1ZSBmb3IuXHJcbiAqIEByZXR1cm4geyp9IC0gVGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgc3BlY2lmaWVkIGtleS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBHZXRGbGFnKGtleVN0cmluZykge1xyXG4gICAgdHJ5IHtcclxuICAgICAgICByZXR1cm4gd2luZG93Ll93YWlscy5mbGFnc1trZXlTdHJpbmddO1xyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byByZXRyaWV2ZSBmbGFnICdcIiArIGtleVN0cmluZyArIFwiJzogXCIgKyBlKTtcclxuICAgIH1cclxufVxyXG4iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5cclxuaW1wb3J0IHtpbnZva2UsIElzV2luZG93c30gZnJvbSBcIi4vc3lzdGVtXCI7XHJcbmltcG9ydCB7R2V0RmxhZ30gZnJvbSBcIi4vZmxhZ3NcIjtcclxuXHJcbi8vIFNldHVwXHJcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xyXG53aW5kb3cuX3dhaWxzLnNldFJlc2l6YWJsZSA9IHNldFJlc2l6YWJsZTtcclxud2luZG93Ll93YWlscy5lbmREcmFnID0gZW5kRHJhZztcclxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIG9uTW91c2VEb3duKTtcclxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG9uTW91c2VNb3ZlKTtcclxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBvbk1vdXNlVXApO1xyXG5cclxuXHJcbmxldCBzaG91bGREcmFnID0gZmFsc2U7XHJcbmxldCByZXNpemVFZGdlID0gbnVsbDtcclxubGV0IHJlc2l6YWJsZSA9IGZhbHNlO1xyXG5sZXQgZGVmYXVsdEN1cnNvciA9IFwiYXV0b1wiO1xyXG5cclxuZnVuY3Rpb24gZHJhZ1Rlc3QoZSkge1xyXG4gICAgbGV0IHZhbCA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGUudGFyZ2V0KS5nZXRQcm9wZXJ0eVZhbHVlKFwiLS13ZWJraXQtYXBwLXJlZ2lvblwiKTtcclxuICAgIGlmICghdmFsIHx8IHZhbCA9PT0gXCJcIiB8fCB2YWwudHJpbSgpICE9PSBcImRyYWdcIiB8fCBlLmJ1dHRvbnMgIT09IDEpIHtcclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZS5kZXRhaWwgPT09IDE7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHNldFJlc2l6YWJsZSh2YWx1ZSkge1xyXG4gICAgcmVzaXphYmxlID0gdmFsdWU7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGVuZERyYWcoKSB7XHJcbiAgICBkb2N1bWVudC5ib2R5LnN0eWxlLmN1cnNvciA9ICdkZWZhdWx0JztcclxuICAgIHNob3VsZERyYWcgPSBmYWxzZTtcclxufVxyXG5cclxuZnVuY3Rpb24gdGVzdFJlc2l6ZSgpIHtcclxuICAgIGlmKCByZXNpemVFZGdlICkge1xyXG4gICAgICAgIGludm9rZShgcmVzaXplOiR7cmVzaXplRWRnZX1gKTtcclxuICAgICAgICByZXR1cm4gdHJ1ZVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG59XHJcblxyXG5mdW5jdGlvbiBvbk1vdXNlRG93bihlKSB7XHJcbiAgICBpZihJc1dpbmRvd3MoKSAmJiB0ZXN0UmVzaXplKCkgfHwgZHJhZ1Rlc3QoZSkpIHtcclxuICAgICAgICBzaG91bGREcmFnID0gISFpc1ZhbGlkRHJhZyhlKTtcclxuICAgIH1cclxufVxyXG5cclxuZnVuY3Rpb24gaXNWYWxpZERyYWcoZSkge1xyXG4gICAgLy8gSWdub3JlIGRyYWcgb24gc2Nyb2xsYmFyc1xyXG4gICAgcmV0dXJuICEoZS5vZmZzZXRYID4gZS50YXJnZXQuY2xpZW50V2lkdGggfHwgZS5vZmZzZXRZID4gZS50YXJnZXQuY2xpZW50SGVpZ2h0KTtcclxufVxyXG5cclxuZnVuY3Rpb24gb25Nb3VzZVVwKGUpIHtcclxuICAgIGxldCBtb3VzZVByZXNzZWQgPSBlLmJ1dHRvbnMgIT09IHVuZGVmaW5lZCA/IGUuYnV0dG9ucyA6IGUud2hpY2g7XHJcbiAgICBpZiAobW91c2VQcmVzc2VkID4gMCkge1xyXG4gICAgICAgIGVuZERyYWcoKTtcclxuICAgIH1cclxufVxyXG5cclxuZnVuY3Rpb24gc2V0UmVzaXplKGN1cnNvciA9IGRlZmF1bHRDdXJzb3IpIHtcclxuICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5jdXJzb3IgPSBjdXJzb3I7XHJcbiAgICByZXNpemVFZGdlID0gY3Vyc29yO1xyXG59XHJcblxyXG5mdW5jdGlvbiBvbk1vdXNlTW92ZShlKSB7XHJcbiAgICBzaG91bGREcmFnID0gY2hlY2tEcmFnKGUpO1xyXG4gICAgaWYgKElzV2luZG93cygpICYmIHJlc2l6YWJsZSkge1xyXG4gICAgICAgIGhhbmRsZVJlc2l6ZShlKTtcclxuICAgIH1cclxufVxyXG5cclxuZnVuY3Rpb24gY2hlY2tEcmFnKGUpIHtcclxuICAgIGxldCBtb3VzZVByZXNzZWQgPSBlLmJ1dHRvbnMgIT09IHVuZGVmaW5lZCA/IGUuYnV0dG9ucyA6IGUud2hpY2g7XHJcbiAgICBpZihzaG91bGREcmFnICYmIG1vdXNlUHJlc3NlZCA+IDApIHtcclxuICAgICAgICBpbnZva2UoXCJkcmFnXCIpO1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIHJldHVybiBzaG91bGREcmFnO1xyXG59XHJcblxyXG5mdW5jdGlvbiBoYW5kbGVSZXNpemUoZSkge1xyXG4gICAgbGV0IHJlc2l6ZUhhbmRsZUhlaWdodCA9IEdldEZsYWcoXCJzeXN0ZW0ucmVzaXplSGFuZGxlSGVpZ2h0XCIpIHx8IDU7XHJcbiAgICBsZXQgcmVzaXplSGFuZGxlV2lkdGggPSBHZXRGbGFnKFwic3lzdGVtLnJlc2l6ZUhhbmRsZVdpZHRoXCIpIHx8IDU7XHJcblxyXG4gICAgLy8gRXh0cmEgcGl4ZWxzIGZvciB0aGUgY29ybmVyIGFyZWFzXHJcbiAgICBsZXQgY29ybmVyRXh0cmEgPSBHZXRGbGFnKFwicmVzaXplQ29ybmVyRXh0cmFcIikgfHwgMTA7XHJcblxyXG4gICAgbGV0IHJpZ2h0Qm9yZGVyID0gd2luZG93Lm91dGVyV2lkdGggLSBlLmNsaWVudFggPCByZXNpemVIYW5kbGVXaWR0aDtcclxuICAgIGxldCBsZWZ0Qm9yZGVyID0gZS5jbGllbnRYIDwgcmVzaXplSGFuZGxlV2lkdGg7XHJcbiAgICBsZXQgdG9wQm9yZGVyID0gZS5jbGllbnRZIDwgcmVzaXplSGFuZGxlSGVpZ2h0O1xyXG4gICAgbGV0IGJvdHRvbUJvcmRlciA9IHdpbmRvdy5vdXRlckhlaWdodCAtIGUuY2xpZW50WSA8IHJlc2l6ZUhhbmRsZUhlaWdodDtcclxuXHJcbiAgICAvLyBBZGp1c3QgZm9yIGNvcm5lcnNcclxuICAgIGxldCByaWdodENvcm5lciA9IHdpbmRvdy5vdXRlcldpZHRoIC0gZS5jbGllbnRYIDwgKHJlc2l6ZUhhbmRsZVdpZHRoICsgY29ybmVyRXh0cmEpO1xyXG4gICAgbGV0IGxlZnRDb3JuZXIgPSBlLmNsaWVudFggPCAocmVzaXplSGFuZGxlV2lkdGggKyBjb3JuZXJFeHRyYSk7XHJcbiAgICBsZXQgdG9wQ29ybmVyID0gZS5jbGllbnRZIDwgKHJlc2l6ZUhhbmRsZUhlaWdodCArIGNvcm5lckV4dHJhKTtcclxuICAgIGxldCBib3R0b21Db3JuZXIgPSB3aW5kb3cub3V0ZXJIZWlnaHQgLSBlLmNsaWVudFkgPCAocmVzaXplSGFuZGxlSGVpZ2h0ICsgY29ybmVyRXh0cmEpO1xyXG5cclxuICAgIC8vIElmIHdlIGFyZW4ndCBvbiBhbiBlZGdlLCBidXQgd2VyZSwgcmVzZXQgdGhlIGN1cnNvciB0byBkZWZhdWx0XHJcbiAgICBpZiAoIWxlZnRCb3JkZXIgJiYgIXJpZ2h0Qm9yZGVyICYmICF0b3BCb3JkZXIgJiYgIWJvdHRvbUJvcmRlciAmJiByZXNpemVFZGdlICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICBzZXRSZXNpemUoKTtcclxuICAgIH1cclxuICAgIC8vIEFkanVzdGVkIGZvciBjb3JuZXIgYXJlYXNcclxuICAgIGVsc2UgaWYgKHJpZ2h0Q29ybmVyICYmIGJvdHRvbUNvcm5lcikgc2V0UmVzaXplKFwic2UtcmVzaXplXCIpO1xyXG4gICAgZWxzZSBpZiAobGVmdENvcm5lciAmJiBib3R0b21Db3JuZXIpIHNldFJlc2l6ZShcInN3LXJlc2l6ZVwiKTtcclxuICAgIGVsc2UgaWYgKGxlZnRDb3JuZXIgJiYgdG9wQ29ybmVyKSBzZXRSZXNpemUoXCJudy1yZXNpemVcIik7XHJcbiAgICBlbHNlIGlmICh0b3BDb3JuZXIgJiYgcmlnaHRDb3JuZXIpIHNldFJlc2l6ZShcIm5lLXJlc2l6ZVwiKTtcclxuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIpIHNldFJlc2l6ZShcInctcmVzaXplXCIpO1xyXG4gICAgZWxzZSBpZiAodG9wQm9yZGVyKSBzZXRSZXNpemUoXCJuLXJlc2l6ZVwiKTtcclxuICAgIGVsc2UgaWYgKGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwicy1yZXNpemVcIik7XHJcbiAgICBlbHNlIGlmIChyaWdodEJvcmRlcikgc2V0UmVzaXplKFwiZS1yZXNpemVcIik7XHJcbn1cclxuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBQb3NpdGlvblxyXG4gKiBAcHJvcGVydHkge251bWJlcn0gWCAtIFRoZSBYIGNvb3JkaW5hdGUuXHJcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBZIC0gVGhlIFkgY29vcmRpbmF0ZS5cclxuICovXHJcblxyXG4vKipcclxuICogQHR5cGVkZWYge09iamVjdH0gU2l6ZVxyXG4gKiBAcHJvcGVydHkge251bWJlcn0gWCAtIFRoZSB3aWR0aC5cclxuICogQHByb3BlcnR5IHtudW1iZXJ9IFkgLSBUaGUgaGVpZ2h0LlxyXG4gKi9cclxuXHJcblxyXG4vKipcclxuICogQHR5cGVkZWYge09iamVjdH0gUmVjdFxyXG4gKiBAcHJvcGVydHkge251bWJlcn0gWCAtIFRoZSBYIGNvb3JkaW5hdGUgb2YgdGhlIHRvcC1sZWZ0IGNvcm5lci5cclxuICogQHByb3BlcnR5IHtudW1iZXJ9IFkgLSBUaGUgWSBjb29yZGluYXRlIG9mIHRoZSB0b3AtbGVmdCBjb3JuZXIuXHJcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBXaWR0aCAtIFRoZSB3aWR0aCBvZiB0aGUgcmVjdGFuZ2xlLlxyXG4gKiBAcHJvcGVydHkge251bWJlcn0gSGVpZ2h0IC0gVGhlIGhlaWdodCBvZiB0aGUgcmVjdGFuZ2xlLlxyXG4gKi9cclxuXHJcblxyXG4vKipcclxuICogQHR5cGVkZWYgeygnWmVybyd8J05pbmV0eSd8J09uZUVpZ2h0eSd8J1R3b1NldmVudHknKX0gUm90YXRpb25cclxuICogVGhlIHJvdGF0aW9uIG9mIHRoZSBzY3JlZW4uIENhbiBiZSBvbmUgb2YgJ1plcm8nLCAnTmluZXR5JywgJ09uZUVpZ2h0eScsICdUd29TZXZlbnR5Jy5cclxuICovXHJcblxyXG5cclxuLyoqXHJcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNjcmVlblxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSWQgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHNjcmVlbi5cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IE5hbWUgLSBIdW1hbiByZWFkYWJsZSBuYW1lIG9mIHRoZSBzY3JlZW4uXHJcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBTY2FsZSAtIFRoZSByZXNvbHV0aW9uIHNjYWxlIG9mIHRoZSBzY3JlZW4uIDEgPSBzdGFuZGFyZCByZXNvbHV0aW9uLCAyID0gaGlnaCAoUmV0aW5hKSwgZXRjLlxyXG4gKiBAcHJvcGVydHkge1Bvc2l0aW9ufSBQb3NpdGlvbiAtIENvbnRhaW5zIHRoZSBYIGFuZCBZIGNvb3JkaW5hdGVzIG9mIHRoZSBzY3JlZW4ncyBwb3NpdGlvbi5cclxuICogQHByb3BlcnR5IHtTaXplfSBTaXplIC0gQ29udGFpbnMgdGhlIHdpZHRoIGFuZCBoZWlnaHQgb2YgdGhlIHNjcmVlbi5cclxuICogQHByb3BlcnR5IHtSZWN0fSBCb3VuZHMgLSBDb250YWlucyB0aGUgYm91bmRzIG9mIHRoZSBzY3JlZW4gaW4gdGVybXMgb2YgWCwgWSwgV2lkdGgsIGFuZCBIZWlnaHQuXHJcbiAqIEBwcm9wZXJ0eSB7UmVjdH0gV29ya0FyZWEgLSBDb250YWlucyB0aGUgYXJlYSBvZiB0aGUgc2NyZWVuIHRoYXQgaXMgYWN0dWFsbHkgdXNhYmxlIChleGNsdWRpbmcgdGFza2JhciBhbmQgb3RoZXIgc3lzdGVtIFVJKS5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBJc1ByaW1hcnkgLSBUcnVlIGlmIHRoaXMgaXMgdGhlIHByaW1hcnkgbW9uaXRvciBzZWxlY3RlZCBieSB0aGUgdXNlciBpbiB0aGUgb3BlcmF0aW5nIHN5c3RlbS5cclxuICogQHByb3BlcnR5IHtSb3RhdGlvbn0gUm90YXRpb24gLSBUaGUgcm90YXRpb24gb2YgdGhlIHNjcmVlbi5cclxuICovXHJcblxyXG5cclxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xyXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5TY3JlZW5zLCAnJyk7XHJcblxyXG5jb25zdCBnZXRBbGwgPSAwO1xyXG5jb25zdCBnZXRQcmltYXJ5ID0gMTtcclxuY29uc3QgZ2V0Q3VycmVudCA9IDI7XHJcblxyXG4vKipcclxuICogR2V0cyBhbGwgc2NyZWVucy5cclxuICogQHJldHVybnMge1Byb21pc2U8U2NyZWVuW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiBTY3JlZW4gb2JqZWN0cy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBHZXRBbGwoKSB7XHJcbiAgICByZXR1cm4gY2FsbChnZXRBbGwpO1xyXG59XHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBwcmltYXJ5IHNjcmVlbi5cclxuICogQHJldHVybnMge1Byb21pc2U8U2NyZWVuPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHByaW1hcnkgc2NyZWVuLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEdldFByaW1hcnkoKSB7XHJcbiAgICByZXR1cm4gY2FsbChnZXRQcmltYXJ5KTtcclxufVxyXG4vKipcclxuICogR2V0cyB0aGUgY3VycmVudCBhY3RpdmUgc2NyZWVuLlxyXG4gKlxyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxTY3JlZW4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjdXJyZW50IGFjdGl2ZSBzY3JlZW4uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gR2V0Q3VycmVudCgpIHtcclxuICAgIHJldHVybiBjYWxsKGdldEN1cnJlbnQpO1xyXG59IiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbi8vIEltcG9ydCBzY3JlZW4ganNkb2MgZGVmaW5pdGlvbiBmcm9tIC4vc2NyZWVucy5qc1xyXG4vKipcclxuICogQHR5cGVkZWYge2ltcG9ydChcIi4vc2NyZWVuc1wiKS5TY3JlZW59IFNjcmVlblxyXG4gKi9cclxuXHJcbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcclxuXHJcbmNvbnN0IGNlbnRlciA9IDA7XHJcbmNvbnN0IHNldFRpdGxlID0gMTtcclxuY29uc3QgZnVsbHNjcmVlbiA9IDI7XHJcbmNvbnN0IHVuRnVsbHNjcmVlbiA9IDM7XHJcbmNvbnN0IHNldFNpemUgPSA0O1xyXG5jb25zdCBzaXplID0gNTtcclxuY29uc3Qgc2V0TWF4U2l6ZSA9IDY7XHJcbmNvbnN0IHNldE1pblNpemUgPSA3O1xyXG5jb25zdCBzZXRBbHdheXNPblRvcCA9IDg7XHJcbmNvbnN0IHNldFJlbGF0aXZlUG9zaXRpb24gPSA5O1xyXG5jb25zdCByZWxhdGl2ZVBvc2l0aW9uID0gMTA7XHJcbmNvbnN0IHNjcmVlbiA9IDExO1xyXG5jb25zdCBoaWRlID0gMTI7XHJcbmNvbnN0IG1heGltaXNlID0gMTM7XHJcbmNvbnN0IHVuTWF4aW1pc2UgPSAxNDtcclxuY29uc3QgdG9nZ2xlTWF4aW1pc2UgPSAxNTtcclxuY29uc3QgbWluaW1pc2UgPSAxNjtcclxuY29uc3QgdW5NaW5pbWlzZSA9IDE3O1xyXG5jb25zdCByZXN0b3JlID0gMTg7XHJcbmNvbnN0IHNob3cgPSAxOTtcclxuY29uc3QgY2xvc2UgPSAyMDtcclxuY29uc3Qgc2V0QmFja2dyb3VuZENvbG91ciA9IDIxO1xyXG5jb25zdCBzZXRSZXNpemFibGUgPSAyMjtcclxuY29uc3Qgd2lkdGggPSAyMztcclxuY29uc3QgaGVpZ2h0ID0gMjQ7XHJcbmNvbnN0IHpvb21JbiA9IDI1O1xyXG5jb25zdCB6b29tT3V0ID0gMjY7XHJcbmNvbnN0IHpvb21SZXNldCA9IDI3O1xyXG5jb25zdCBnZXRab29tTGV2ZWwgPSAyODtcclxuY29uc3Qgc2V0Wm9vbUxldmVsID0gMjk7XHJcblxyXG5jb25zdCB0aGlzV2luZG93ID0gR2V0KCcnKTtcclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVdpbmRvdyhjYWxsKSB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIEdldDogKHdpbmRvd05hbWUpID0+IGNyZWF0ZVdpbmRvdyhuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLldpbmRvdywgd2luZG93TmFtZSkpLFxyXG4gICAgICAgIENlbnRlcjogKCkgPT4gY2FsbChjZW50ZXIpLFxyXG4gICAgICAgIFNldFRpdGxlOiAodGl0bGUpID0+IGNhbGwoc2V0VGl0bGUsIHt0aXRsZX0pLFxyXG4gICAgICAgIEZ1bGxzY3JlZW46ICgpID0+IGNhbGwoZnVsbHNjcmVlbiksXHJcbiAgICAgICAgVW5GdWxsc2NyZWVuOiAoKSA9PiBjYWxsKHVuRnVsbHNjcmVlbiksXHJcbiAgICAgICAgU2V0U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcclxuICAgICAgICBTaXplOiAoKSA9PiBjYWxsKHNpemUpLFxyXG4gICAgICAgIFNldE1heFNpemU6ICh3aWR0aCwgaGVpZ2h0KSA9PiBjYWxsKHNldE1heFNpemUsIHt3aWR0aCwgaGVpZ2h0fSksXHJcbiAgICAgICAgU2V0TWluU2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWluU2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcclxuICAgICAgICBTZXRBbHdheXNPblRvcDogKG9uVG9wKSA9PiBjYWxsKHNldEFsd2F5c09uVG9wLCB7YWx3YXlzT25Ub3A6IG9uVG9wfSksXHJcbiAgICAgICAgU2V0UmVsYXRpdmVQb3NpdGlvbjogKHgsIHkpID0+IGNhbGwoc2V0UmVsYXRpdmVQb3NpdGlvbiwge3gsIHl9KSxcclxuICAgICAgICBSZWxhdGl2ZVBvc2l0aW9uOiAoKSA9PiBjYWxsKHJlbGF0aXZlUG9zaXRpb24pLFxyXG4gICAgICAgIFNjcmVlbjogKCkgPT4gY2FsbChzY3JlZW4pLFxyXG4gICAgICAgIEhpZGU6ICgpID0+IGNhbGwoaGlkZSksXHJcbiAgICAgICAgTWF4aW1pc2U6ICgpID0+IGNhbGwobWF4aW1pc2UpLFxyXG4gICAgICAgIFVuTWF4aW1pc2U6ICgpID0+IGNhbGwodW5NYXhpbWlzZSksXHJcbiAgICAgICAgVG9nZ2xlTWF4aW1pc2U6ICgpID0+IGNhbGwodG9nZ2xlTWF4aW1pc2UpLFxyXG4gICAgICAgIE1pbmltaXNlOiAoKSA9PiBjYWxsKG1pbmltaXNlKSxcclxuICAgICAgICBVbk1pbmltaXNlOiAoKSA9PiBjYWxsKHVuTWluaW1pc2UpLFxyXG4gICAgICAgIFJlc3RvcmU6ICgpID0+IGNhbGwocmVzdG9yZSksXHJcbiAgICAgICAgU2hvdzogKCkgPT4gY2FsbChzaG93KSxcclxuICAgICAgICBDbG9zZTogKCkgPT4gY2FsbChjbG9zZSksXHJcbiAgICAgICAgU2V0QmFja2dyb3VuZENvbG91cjogKHIsIGcsIGIsIGEpID0+IGNhbGwoc2V0QmFja2dyb3VuZENvbG91ciwge3IsIGcsIGIsIGF9KSxcclxuICAgICAgICBTZXRSZXNpemFibGU6IChyZXNpemFibGUpID0+IGNhbGwoc2V0UmVzaXphYmxlLCB7cmVzaXphYmxlfSksXHJcbiAgICAgICAgV2lkdGg6ICgpID0+IGNhbGwod2lkdGgpLFxyXG4gICAgICAgIEhlaWdodDogKCkgPT4gY2FsbChoZWlnaHQpLFxyXG4gICAgICAgIFpvb21JbjogKCkgPT4gY2FsbCh6b29tSW4pLFxyXG4gICAgICAgIFpvb21PdXQ6ICgpID0+IGNhbGwoem9vbU91dCksXHJcbiAgICAgICAgWm9vbVJlc2V0OiAoKSA9PiBjYWxsKHpvb21SZXNldCksXHJcbiAgICAgICAgR2V0Wm9vbUxldmVsOiAoKSA9PiBjYWxsKGdldFpvb21MZXZlbCksXHJcbiAgICAgICAgU2V0Wm9vbUxldmVsOiAoem9vbUxldmVsKSA9PiBjYWxsKHNldFpvb21MZXZlbCwge3pvb21MZXZlbH0pLFxyXG4gICAgfTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIHNwZWNpZmllZCB3aW5kb3cuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSB3aW5kb3dOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHdpbmRvdyB0byBnZXQuXHJcbiAqIEByZXR1cm4ge09iamVjdH0gLSBUaGUgc3BlY2lmaWVkIHdpbmRvdyBvYmplY3QuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gR2V0KHdpbmRvd05hbWUpIHtcclxuICAgIHJldHVybiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENlbnRlcnMgdGhlIHdpbmRvdyBvbiB0aGUgc2NyZWVuLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIENlbnRlcigpIHtcclxuICAgIHRoaXNXaW5kb3cuQ2VudGVyKCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXRzIHRoZSB0aXRsZSBvZiB0aGUgd2luZG93LlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGUgLSBUaGUgdGl0bGUgdG8gc2V0LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldFRpdGxlKHRpdGxlKSB7XHJcbiAgICB0aGlzV2luZG93LlNldFRpdGxlKHRpdGxlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIHdpbmRvdyB0byBmdWxsc2NyZWVuLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEZ1bGxzY3JlZW4oKSB7XHJcbiAgICB0aGlzV2luZG93LkZ1bGxzY3JlZW4oKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIHNpemUgb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgLSBUaGUgaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2V0U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XHJcbiAgICB0aGlzV2luZG93LlNldFNpemUod2lkdGgsIGhlaWdodCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBzaXplIG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2l6ZSgpIHtcclxuICAgIHJldHVybiB0aGlzV2luZG93LlNpemUoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93LlxyXG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGggLSBUaGUgbWF4aW11bSB3aWR0aCBvZiB0aGUgd2luZG93LlxyXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIG1heGltdW0gaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XHJcbiAgICB0aGlzV2luZG93LlNldE1heFNpemUod2lkdGgsIGhlaWdodCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXRzIHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIG1pbmltdW0gd2lkdGggb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodCAtIFRoZSBtaW5pbXVtIGhlaWdodCBvZiB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldE1pblNpemUod2lkdGgsIGhlaWdodCkge1xyXG4gICAgdGhpc1dpbmRvdy5TZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgd2luZG93IHRvIGFsd2F5cyBiZSBvbiB0b3AuXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gb25Ub3AgLSBXaGV0aGVyIHRoZSB3aW5kb3cgc2hvdWxkIGFsd2F5cyBiZSBvbiB0b3AuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2V0QWx3YXlzT25Ub3Aob25Ub3ApIHtcclxuICAgIHRoaXNXaW5kb3cuU2V0QWx3YXlzT25Ub3Aob25Ub3ApO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHggLSBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSB3aW5kb3cncyBwb3NpdGlvbi5cclxuICogQHBhcmFtIHtudW1iZXJ9IHkgLSBUaGUgeS1jb29yZGluYXRlIG9mIHRoZSB3aW5kb3cncyBwb3NpdGlvbi5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTZXRSZWxhdGl2ZVBvc2l0aW9uKHgsIHkpIHtcclxuICAgIHRoaXNXaW5kb3cuU2V0UmVsYXRpdmVQb3NpdGlvbih4LCB5KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gUmVsYXRpdmVQb3NpdGlvbigpIHtcclxuICAgIHJldHVybiB0aGlzV2luZG93LlJlbGF0aXZlUG9zaXRpb24oKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIHNjcmVlbiB0aGF0IHRoZSB3aW5kb3cgaXMgb24uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2NyZWVuKCkge1xyXG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2NyZWVuKCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBIaWRlcyB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XHJcbiAgICB0aGlzV2luZG93LkhpZGUoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE1heGltaXNlcyB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIE1heGltaXNlKCkge1xyXG4gICAgdGhpc1dpbmRvdy5NYXhpbWlzZSgpO1xyXG59XHJcblxyXG4vKipcclxuICogVW4tbWF4aW1pc2VzIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gVW5NYXhpbWlzZSgpIHtcclxuICAgIHRoaXNXaW5kb3cuVW5NYXhpbWlzZSgpO1xyXG59XHJcblxyXG4vKipcclxuICogVG9nZ2xlcyB0aGUgbWF4aW1pc2F0aW9uIG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gVG9nZ2xlTWF4aW1pc2UoKSB7XHJcbiAgICB0aGlzV2luZG93LlRvZ2dsZU1heGltaXNlKCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBNaW5pbWlzZXMgdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBNaW5pbWlzZSgpIHtcclxuICAgIHRoaXNXaW5kb3cuTWluaW1pc2UoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFVuLW1pbmltaXNlcyB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFVuTWluaW1pc2UoKSB7XHJcbiAgICB0aGlzV2luZG93LlVuTWluaW1pc2UoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlc3RvcmVzIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gUmVzdG9yZSgpIHtcclxuICAgIHRoaXNXaW5kb3cuUmVzdG9yZSgpO1xyXG59XHJcblxyXG4vKipcclxuICogU2hvd3MgdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTaG93KCkge1xyXG4gICAgdGhpc1dpbmRvdy5TaG93KCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDbG9zZXMgdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBDbG9zZSgpIHtcclxuICAgIHRoaXNXaW5kb3cuQ2xvc2UoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIGJhY2tncm91bmQgY29sb3VyIG9mIHRoZSB3aW5kb3cuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSByIC0gVGhlIHJlZCBjb21wb25lbnQgb2YgdGhlIGNvbG91ci5cclxuICogQHBhcmFtIHtudW1iZXJ9IGcgLSBUaGUgZ3JlZW4gY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIC0gVGhlIGJsdWUgY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIC0gVGhlIGFscGhhIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldEJhY2tncm91bmRDb2xvdXIociwgZywgYiwgYSkge1xyXG4gICAgdGhpc1dpbmRvdy5TZXRCYWNrZ3JvdW5kQ29sb3VyKHIsIGcsIGIsIGEpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgcmVzaXphYmxlLlxyXG4gKiBAcGFyYW0ge2Jvb2xlYW59IHJlc2l6YWJsZSAtIFdoZXRoZXIgdGhlIHdpbmRvdyBzaG91bGQgYmUgcmVzaXphYmxlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldFJlc2l6YWJsZShyZXNpemFibGUpIHtcclxuICAgIHRoaXNXaW5kb3cuU2V0UmVzaXphYmxlKHJlc2l6YWJsZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSB3aWR0aCBvZiB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpZHRoKCkge1xyXG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuV2lkdGgoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEhlaWdodCgpIHtcclxuICAgIHJldHVybiB0aGlzV2luZG93LkhlaWdodCgpO1xyXG59XHJcblxyXG4vKipcclxuICogWm9vbXMgaW4gdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBab29tSW4oKSB7XHJcbiAgICB0aGlzV2luZG93Llpvb21JbigpO1xyXG59XHJcblxyXG4vKipcclxuICogWm9vbXMgb3V0IHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gWm9vbU91dCgpIHtcclxuICAgIHRoaXNXaW5kb3cuWm9vbU91dCgpO1xyXG59XHJcblxyXG4vKipcclxuICogUmVzZXRzIHRoZSB6b29tIG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gWm9vbVJlc2V0KCkge1xyXG4gICAgdGhpc1dpbmRvdy5ab29tUmVzZXQoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBHZXRab29tTGV2ZWwoKSB7XHJcbiAgICByZXR1cm4gdGhpc1dpbmRvdy5HZXRab29tTGV2ZWwoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHpvb21MZXZlbCAtIFRoZSB6b29tIGxldmVsIHRvIHNldC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTZXRab29tTGV2ZWwoem9vbUxldmVsKSB7XHJcbiAgICB0aGlzV2luZG93LlNldFpvb21MZXZlbCh6b29tTGV2ZWwpO1xyXG59XHJcbiIsICJcclxuaW1wb3J0IHtFbWl0LCBXYWlsc0V2ZW50fSBmcm9tIFwiLi9ldmVudHNcIjtcclxuaW1wb3J0IHtRdWVzdGlvbn0gZnJvbSBcIi4vZGlhbG9nc1wiO1xyXG5pbXBvcnQge0dldH0gZnJvbSBcIi4vd2luZG93XCI7XHJcbmltcG9ydCB7T3BlblVSTH0gZnJvbSBcIi4vYnJvd3NlclwiO1xyXG5cclxuLyoqXHJcbiAqIFNlbmRzIGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIG9wdGlvbmFsIGRhdGEuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gc2VuZC5cclxuICogQHBhcmFtIHthbnl9IFtkYXRhPW51bGxdIC0gT3B0aW9uYWwgZGF0YSB0byBzZW5kIGFsb25nIHdpdGggdGhlIGV2ZW50LlxyXG4gKlxyXG4gKiBAcmV0dXJuIHt2b2lkfVxyXG4gKi9cclxuZnVuY3Rpb24gc2VuZEV2ZW50KGV2ZW50TmFtZSwgZGF0YT1udWxsKSB7XHJcbiAgICBsZXQgZXZlbnQgPSBuZXcgV2FpbHNFdmVudChldmVudE5hbWUsIGRhdGEpO1xyXG4gICAgRW1pdChldmVudCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBBZGRzIGV2ZW50IGxpc3RlbmVycyB0byBlbGVtZW50cyB3aXRoIGB3bWwtZXZlbnRgIGF0dHJpYnV0ZS5cclxuICpcclxuICogQHJldHVybiB7dm9pZH1cclxuICovXHJcbmZ1bmN0aW9uIGFkZFdNTEV2ZW50TGlzdGVuZXJzKCkge1xyXG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLWV2ZW50XScpO1xyXG4gICAgZWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbiAoZWxlbWVudCkge1xyXG4gICAgICAgIGNvbnN0IGV2ZW50VHlwZSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtZXZlbnQnKTtcclxuICAgICAgICBjb25zdCBjb25maXJtID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1jb25maXJtJyk7XHJcbiAgICAgICAgY29uc3QgdHJpZ2dlciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdHJpZ2dlcicpIHx8IFwiY2xpY2tcIjtcclxuXHJcbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAoY29uZmlybSkge1xyXG4gICAgICAgICAgICAgICAgUXVlc3Rpb24oe1RpdGxlOiBcIkNvbmZpcm1cIiwgTWVzc2FnZTpjb25maXJtLCBEZXRhY2hlZDogZmFsc2UsIEJ1dHRvbnM6W3tMYWJlbDpcIlllc1wifSx7TGFiZWw6XCJOb1wiLCBJc0RlZmF1bHQ6dHJ1ZX1dfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPT0gXCJOb1wiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbmRFdmVudChldmVudFR5cGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHNlbmRFdmVudChldmVudFR5cGUpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8vIFJlbW92ZSBleGlzdGluZyBsaXN0ZW5lcnNcclxuICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xyXG5cclxuICAgICAgICAvLyBBZGQgbmV3IGxpc3RlbmVyXHJcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqIENhbGxzIGEgbWV0aG9kIG9uIGEgc3BlY2lmaWVkIHdpbmRvdy5cclxuICogQHBhcmFtIHtzdHJpbmd9IHdpbmRvd05hbWUgLSBUaGUgbmFtZSBvZiB0aGUgd2luZG93IHRvIGNhbGwgdGhlIG1ldGhvZCBvbi5cclxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZCAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cclxuICovXHJcbmZ1bmN0aW9uIGNhbGxXaW5kb3dNZXRob2Qod2luZG93TmFtZSwgbWV0aG9kKSB7XHJcbiAgICBsZXQgdGFyZ2V0V2luZG93ID0gR2V0KHdpbmRvd05hbWUpO1xyXG4gICAgbGV0IG1ldGhvZE1hcCA9IFdpbmRvd01ldGhvZHModGFyZ2V0V2luZG93KTtcclxuICAgIGlmICghbWV0aG9kTWFwLmhhcyhtZXRob2QpKSB7XHJcbiAgICAgICAgY29uc29sZS5sb2coXCJXaW5kb3cgbWV0aG9kIFwiICsgbWV0aG9kICsgXCIgbm90IGZvdW5kXCIpO1xyXG4gICAgfVxyXG4gICAgdHJ5IHtcclxuICAgICAgICBtZXRob2RNYXAuZ2V0KG1ldGhvZCkoKTtcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgY2FsbGluZyB3aW5kb3cgbWV0aG9kICdcIiArIG1ldGhvZCArIFwiJzogXCIgKyBlKTtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEFkZHMgd2luZG93IGxpc3RlbmVycyBmb3IgZWxlbWVudHMgd2l0aCB0aGUgJ3dtbC13aW5kb3cnIGF0dHJpYnV0ZS5cclxuICogUmVtb3ZlcyBhbnkgZXhpc3RpbmcgbGlzdGVuZXJzIGJlZm9yZSBhZGRpbmcgbmV3IG9uZXMuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3ZvaWR9XHJcbiAqL1xyXG5mdW5jdGlvbiBhZGRXTUxXaW5kb3dMaXN0ZW5lcnMoKSB7XHJcbiAgICBjb25zdCBlbGVtZW50cyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ1t3bWwtd2luZG93XScpO1xyXG4gICAgZWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbiAoZWxlbWVudCkge1xyXG4gICAgICAgIGNvbnN0IHdpbmRvd01ldGhvZCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtd2luZG93Jyk7XHJcbiAgICAgICAgY29uc3QgY29uZmlybSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtY29uZmlybScpO1xyXG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCAnY2xpY2snO1xyXG4gICAgICAgIGNvbnN0IHRhcmdldFdpbmRvdyA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdGFyZ2V0LXdpbmRvdycpIHx8ICcnO1xyXG5cclxuICAgICAgICBsZXQgY2FsbGJhY2sgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChjb25maXJtKSB7XHJcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIEJ1dHRvbnM6W3tMYWJlbDpcIlllc1wifSx7TGFiZWw6XCJOb1wiLCBJc0RlZmF1bHQ6dHJ1ZX1dfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPT0gXCJOb1wiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxXaW5kb3dNZXRob2QodGFyZ2V0V2luZG93LCB3aW5kb3dNZXRob2QpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNhbGxXaW5kb3dNZXRob2QodGFyZ2V0V2luZG93LCB3aW5kb3dNZXRob2QpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8vIFJlbW92ZSBleGlzdGluZyBsaXN0ZW5lcnNcclxuICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xyXG5cclxuICAgICAgICAvLyBBZGQgbmV3IGxpc3RlbmVyXHJcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogQWRkcyBhIGxpc3RlbmVyIHRvIGVsZW1lbnRzIHdpdGggdGhlICd3bWwtb3BlbnVybCcgYXR0cmlidXRlLlxyXG4gKiBXaGVuIHRoZSBzcGVjaWZpZWQgdHJpZ2dlciBldmVudCBpcyBmaXJlZCBvbiBhbnkgb2YgdGhlc2UgZWxlbWVudHMsXHJcbiAqIHRoZSBsaXN0ZW5lciB3aWxsIG9wZW4gdGhlIFVSTCBzcGVjaWZpZWQgYnkgdGhlICd3bWwtb3BlbnVybCcgYXR0cmlidXRlLlxyXG4gKiBJZiBhICd3bWwtY29uZmlybScgYXR0cmlidXRlIGlzIHByb3ZpZGVkLCBhIGNvbmZpcm1hdGlvbiBkaWFsb2cgd2lsbCBiZSBkaXNwbGF5ZWQsXHJcbiAqIGFuZCB0aGUgVVJMIHdpbGwgb25seSBiZSBvcGVuZWQgaWYgdGhlIHVzZXIgY29uZmlybXMuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3ZvaWR9XHJcbiAqL1xyXG5mdW5jdGlvbiBhZGRXTUxPcGVuQnJvd3Nlckxpc3RlbmVyKCkge1xyXG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLW9wZW51cmxdJyk7XHJcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChlbGVtZW50KSB7XHJcbiAgICAgICAgY29uc3QgdXJsID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1vcGVudXJsJyk7XHJcbiAgICAgICAgY29uc3QgY29uZmlybSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtY29uZmlybScpO1xyXG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XHJcblxyXG4gICAgICAgIGxldCBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcclxuICAgICAgICAgICAgICAgIFF1ZXN0aW9uKHtUaXRsZTogXCJDb25maXJtXCIsIE1lc3NhZ2U6Y29uZmlybSwgQnV0dG9uczpbe0xhYmVsOlwiWWVzXCJ9LHtMYWJlbDpcIk5vXCIsIElzRGVmYXVsdDp0cnVlfV19KS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9PSBcIk5vXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCBPcGVuVVJMKHVybCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdm9pZCBPcGVuVVJMKHVybCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgLy8gUmVtb3ZlIGV4aXN0aW5nIGxpc3RlbmVyc1xyXG4gICAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XHJcblxyXG4gICAgICAgIC8vIEFkZCBuZXcgbGlzdGVuZXJcclxuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZWxvYWRzIHRoZSBXTUwgcGFnZSBieSBhZGRpbmcgbmVjZXNzYXJ5IGV2ZW50IGxpc3RlbmVycyBhbmQgYnJvd3NlciBsaXN0ZW5lcnMuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3ZvaWR9XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gUmVsb2FkKCkge1xyXG4gICAgYWRkV01MRXZlbnRMaXN0ZW5lcnMoKTtcclxuICAgIGFkZFdNTFdpbmRvd0xpc3RlbmVycygpO1xyXG4gICAgYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpO1xyXG59XHJcblxyXG4vKipcclxuICogUmV0dXJucyBhIG1hcCBvZiBhbGwgbWV0aG9kcyBpbiB0aGUgY3VycmVudCB3aW5kb3cuXHJcbiAqIEByZXR1cm5zIHtNYXB9IC0gQSBtYXAgb2Ygd2luZG93IG1ldGhvZHMuXHJcbiAqL1xyXG5mdW5jdGlvbiBXaW5kb3dNZXRob2RzKHRhcmdldFdpbmRvdykge1xyXG4gICAgLy8gQ3JlYXRlIGEgbmV3IG1hcCB0byBzdG9yZSBtZXRob2RzXHJcbiAgICBsZXQgcmVzdWx0ID0gbmV3IE1hcCgpO1xyXG5cclxuICAgIC8vIEl0ZXJhdGUgb3ZlciBhbGwgcHJvcGVydGllcyBvZiB0aGUgd2luZG93IG9iamVjdFxyXG4gICAgZm9yIChsZXQgbWV0aG9kIGluIHRhcmdldFdpbmRvdykge1xyXG4gICAgICAgIC8vIENoZWNrIGlmIHRoZSBwcm9wZXJ0eSBpcyBpbmRlZWQgYSBtZXRob2QgKGZ1bmN0aW9uKVxyXG4gICAgICAgIGlmKHR5cGVvZiB0YXJnZXRXaW5kb3dbbWV0aG9kXSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgICAvLyBBZGQgdGhlIG1ldGhvZCB0byB0aGUgbWFwXHJcbiAgICAgICAgICAgIHJlc3VsdC5zZXQobWV0aG9kLCB0YXJnZXRXaW5kb3dbbWV0aG9kXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgIH1cclxuICAgIC8vIFJldHVybiB0aGUgbWFwIG9mIHdpbmRvdyBtZXRob2RzXHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59IiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7aW1wb3J0KFwiLi90eXBlc1wiKS5XYWlsc0V2ZW50fSBXYWlsc0V2ZW50XHJcbiAqL1xyXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcblxyXG5pbXBvcnQge0V2ZW50VHlwZXN9IGZyb20gXCIuL2V2ZW50X3R5cGVzXCI7XHJcbmV4cG9ydCBjb25zdCBUeXBlcyA9IEV2ZW50VHlwZXM7XHJcblxyXG4vLyBTZXR1cFxyXG53aW5kb3cuX3dhaWxzID0gd2luZG93Ll93YWlscyB8fCB7fTtcclxud2luZG93Ll93YWlscy5kaXNwYXRjaFdhaWxzRXZlbnQgPSBkaXNwYXRjaFdhaWxzRXZlbnQ7XHJcblxyXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5FdmVudHMsICcnKTtcclxuY29uc3QgRW1pdE1ldGhvZCA9IDA7XHJcbmNvbnN0IGV2ZW50TGlzdGVuZXJzID0gbmV3IE1hcCgpO1xyXG5cclxuY2xhc3MgTGlzdGVuZXIge1xyXG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XHJcbiAgICAgICAgdGhpcy5ldmVudE5hbWUgPSBldmVudE5hbWU7XHJcbiAgICAgICAgdGhpcy5tYXhDYWxsYmFja3MgPSBtYXhDYWxsYmFja3MgfHwgLTE7XHJcbiAgICAgICAgdGhpcy5DYWxsYmFjayA9IChkYXRhKSA9PiB7XHJcbiAgICAgICAgICAgIGNhbGxiYWNrKGRhdGEpO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhDYWxsYmFja3MgPT09IC0xKSByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIHRoaXMubWF4Q2FsbGJhY2tzIC09IDE7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heENhbGxiYWNrcyA9PT0gMDtcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgV2FpbHNFdmVudCB7XHJcbiAgICBjb25zdHJ1Y3RvcihuYW1lLCBkYXRhID0gbnVsbCkge1xyXG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XHJcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIHNldHVwKCkge1xyXG59XHJcblxyXG5mdW5jdGlvbiBkaXNwYXRjaFdhaWxzRXZlbnQoZXZlbnQpIHtcclxuICAgIGxldCBsaXN0ZW5lcnMgPSBldmVudExpc3RlbmVycy5nZXQoZXZlbnQubmFtZSk7XHJcbiAgICBpZiAobGlzdGVuZXJzKSB7XHJcbiAgICAgICAgbGV0IHRvUmVtb3ZlID0gbGlzdGVuZXJzLmZpbHRlcihsaXN0ZW5lciA9PiB7XHJcbiAgICAgICAgICAgIGxldCByZW1vdmUgPSBsaXN0ZW5lci5DYWxsYmFjayhldmVudCk7XHJcbiAgICAgICAgICAgIGlmIChyZW1vdmUpIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGlmICh0b1JlbW92ZS5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVycy5maWx0ZXIobCA9PiAhdG9SZW1vdmUuaW5jbHVkZXMobCkpO1xyXG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkgZXZlbnRMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50Lm5hbWUpO1xyXG4gICAgICAgICAgICBlbHNlIGV2ZW50TGlzdGVuZXJzLnNldChldmVudC5uYW1lLCBsaXN0ZW5lcnMpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzIGZvciBhIHNwZWNpZmljIGV2ZW50LlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmb3IuXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3MgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdGhlIGNhbGxiYWNrIGNhbiBiZSBjYWxsZWQgZm9yIHRoZSBldmVudC4gT25jZSB0aGUgbWF4aW11bSBudW1iZXIgaXMgcmVhY2hlZCwgdGhlIGNhbGxiYWNrIHdpbGwgbm8gbG9uZ2VyIGJlIGNhbGxlZC5cclxuICpcclxuIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpIHtcclxuICAgIGxldCBsaXN0ZW5lcnMgPSBldmVudExpc3RlbmVycy5nZXQoZXZlbnROYW1lKSB8fCBbXTtcclxuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xyXG4gICAgbGlzdGVuZXJzLnB1c2godGhpc0xpc3RlbmVyKTtcclxuICAgIGV2ZW50TGlzdGVuZXJzLnNldChldmVudE5hbWUsIGxpc3RlbmVycyk7XHJcbiAgICByZXR1cm4gKCkgPT4gbGlzdGVuZXJPZmYodGhpc0xpc3RlbmVyKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdGVycyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIHNwZWNpZmllZCBldmVudCBvY2N1cnMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkLiBJdCB0YWtlcyBubyBwYXJhbWV0ZXJzLlxyXG4gKiBAcmV0dXJuIHtmdW5jdGlvbn0gLSBBIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCB3aWxsIHVucmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZyb20gdGhlIGV2ZW50LiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gT24oZXZlbnROYW1lLCBjYWxsYmFjaykgeyByZXR1cm4gT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAtMSk7IH1cclxuXHJcbi8qKlxyXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmx5IG9uY2UgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGV2ZW50IG9jY3Vycy5cclxuICogQHJldHVybiB7ZnVuY3Rpb259IC0gQSBmdW5jdGlvbiB0aGF0LCB3aGVuIGNhbGxlZCwgd2lsbCB1bnJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmcm9tIHRoZSBldmVudC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHsgcmV0dXJuIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgMSk7IH1cclxuXHJcbi8qKlxyXG4gKiBSZW1vdmVzIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIgZnJvbSB0aGUgZXZlbnQgbGlzdGVuZXJzIGNvbGxlY3Rpb24uXHJcbiAqIElmIGFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBldmVudCBhcmUgcmVtb3ZlZCwgdGhlIGV2ZW50IGtleSBpcyBkZWxldGVkIGZyb20gdGhlIGNvbGxlY3Rpb24uXHJcbiAqXHJcbiAqIEBwYXJhbSB7T2JqZWN0fSBsaXN0ZW5lciAtIFRoZSBsaXN0ZW5lciB0byBiZSByZW1vdmVkLlxyXG4gKi9cclxuZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXIpIHtcclxuICAgIGNvbnN0IGV2ZW50TmFtZSA9IGxpc3RlbmVyLmV2ZW50TmFtZTtcclxuICAgIGxldCBsaXN0ZW5lcnMgPSBldmVudExpc3RlbmVycy5nZXQoZXZlbnROYW1lKS5maWx0ZXIobCA9PiBsICE9PSBsaXN0ZW5lcik7XHJcbiAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkgZXZlbnRMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSk7XHJcbiAgICBlbHNlIGV2ZW50TGlzdGVuZXJzLnNldChldmVudE5hbWUsIGxpc3RlbmVycyk7XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogUmVtb3ZlcyBldmVudCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQgbmFtZXMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGxpc3RlbmVycyBmb3IuXHJcbiAqIEBwYXJhbSB7Li4uc3RyaW5nfSBhZGRpdGlvbmFsRXZlbnROYW1lcyAtIEFkZGl0aW9uYWwgZXZlbnQgbmFtZXMgdG8gcmVtb3ZlIGxpc3RlbmVycyBmb3IuXHJcbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBPZmYoZXZlbnROYW1lLCAuLi5hZGRpdGlvbmFsRXZlbnROYW1lcykge1xyXG4gICAgbGV0IGV2ZW50c1RvUmVtb3ZlID0gW2V2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXNdO1xyXG4gICAgZXZlbnRzVG9SZW1vdmUuZm9yRWFjaChldmVudE5hbWUgPT4gZXZlbnRMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSkpO1xyXG59XHJcbi8qKlxyXG4gKiBSZW1vdmVzIGFsbCBldmVudCBsaXN0ZW5lcnMuXHJcbiAqXHJcbiAqIEBmdW5jdGlvbiBPZmZBbGxcclxuICogQHJldHVybnMge3ZvaWR9XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gT2ZmQWxsKCkgeyBldmVudExpc3RlbmVycy5jbGVhcigpOyB9XHJcblxyXG4vKipcclxuICogRW1pdHMgYW4gZXZlbnQgdXNpbmcgdGhlIGdpdmVuIGV2ZW50IG5hbWUuXHJcbiAqXHJcbiAqIEBwYXJhbSB7V2FpbHNFdmVudH0gZXZlbnQgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdC5cclxuICogQHJldHVybnMge2FueX0gLSBUaGUgcmVzdWx0IG9mIHRoZSBlbWl0dGVkIGV2ZW50LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEVtaXQoZXZlbnQpIHsgcmV0dXJuIGNhbGwoRW1pdE1ldGhvZCwgZXZlbnQpOyB9XHJcbiIsICJcbmV4cG9ydCBjb25zdCBFdmVudFR5cGVzID0ge1xuXHRXaW5kb3dzOiB7XG5cdFx0U3lzdGVtVGhlbWVDaGFuZ2VkOiBcIndpbmRvd3M6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdFx0QVBNUG93ZXJTdGF0dXNDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclN0YXR1c0NoYW5nZVwiLFxuXHRcdEFQTVN1c3BlbmQ6IFwid2luZG93czpBUE1TdXNwZW5kXCIsXG5cdFx0QVBNUmVzdW1lQXV0b21hdGljOiBcIndpbmRvd3M6QVBNUmVzdW1lQXV0b21hdGljXCIsXG5cdFx0QVBNUmVzdW1lU3VzcGVuZDogXCJ3aW5kb3dzOkFQTVJlc3VtZVN1c3BlbmRcIixcblx0XHRBUE1Qb3dlclNldHRpbmdDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclNldHRpbmdDaGFuZ2VcIixcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwid2luZG93czpBcHBsaWNhdGlvblN0YXJ0ZWRcIixcblx0XHRXZWJWaWV3TmF2aWdhdGlvbkNvbXBsZXRlZDogXCJ3aW5kb3dzOldlYlZpZXdOYXZpZ2F0aW9uQ29tcGxldGVkXCIsXG5cdFx0V2luZG93SW5hY3RpdmU6IFwid2luZG93czpXaW5kb3dJbmFjdGl2ZVwiLFxuXHRcdFdpbmRvd0FjdGl2ZTogXCJ3aW5kb3dzOldpbmRvd0FjdGl2ZVwiLFxuXHRcdFdpbmRvd0NsaWNrQWN0aXZlOiBcIndpbmRvd3M6V2luZG93Q2xpY2tBY3RpdmVcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcIndpbmRvd3M6V2luZG93RnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1VuRnVsbHNjcmVlbjogXCJ3aW5kb3dzOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwid2luZG93czpXaW5kb3dSZXN0b3JlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwid2luZG93czpXaW5kb3dNaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWluaW1pc2U6IFwid2luZG93czpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2U6IFwid2luZG93czpXaW5kb3dDbG9zZVwiLFxuXHRcdFdpbmRvd1NldEZvY3VzOiBcIndpbmRvd3M6V2luZG93U2V0Rm9jdXNcIixcblx0XHRXaW5kb3dLaWxsRm9jdXM6IFwid2luZG93czpXaW5kb3dLaWxsRm9jdXNcIixcblx0XHRXaW5kb3dEcmFnRHJvcDogXCJ3aW5kb3dzOldpbmRvd0RyYWdEcm9wXCIsXG5cdFx0V2luZG93RHJhZ0VudGVyOiBcIndpbmRvd3M6V2luZG93RHJhZ0VudGVyXCIsXG5cdFx0V2luZG93RHJhZ0xlYXZlOiBcIndpbmRvd3M6V2luZG93RHJhZ0xlYXZlXCIsXG5cdFx0V2luZG93RHJhZ092ZXI6IFwid2luZG93czpXaW5kb3dEcmFnT3ZlclwiLFxuXHR9LFxuXHRNYWM6IHtcblx0XHRBcHBsaWNhdGlvbkRpZEJlY29tZUFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUVmZmVjdGl2ZUFwcGVhcmFuY2VcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUljb246IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlSWNvblwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU2NyZWVuUGFyYW1ldGVyc1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uXCIsXG5cdFx0QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmc6IFwibWFjOkFwcGxpY2F0aW9uRGlkRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25EaWRIaWRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZEhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFJlc2lnbkFjdGl2ZU5vdGlmaWNhdGlvbjogXCJtYWM6QXBwbGljYXRpb25EaWRSZXNpZ25BY3RpdmVOb3RpZmljYXRpb25cIixcblx0XHRBcHBsaWNhdGlvbkRpZFVuaGlkZTogXCJtYWM6QXBwbGljYXRpb25EaWRVbmhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25EaWRVcGRhdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxCZWNvbWVBY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbEJlY29tZUFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEZpbmlzaExhdW5jaGluZzogXCJtYWM6QXBwbGljYXRpb25XaWxsRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsSGlkZTogXCJtYWM6QXBwbGljYXRpb25XaWxsSGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFJlc2lnbkFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVGVybWluYXRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxVbmhpZGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFVuaGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsVXBkYXRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZTogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZSFcIixcblx0XHRBcHBsaWNhdGlvblNob3VsZEhhbmRsZVJlb3BlbjogXCJtYWM6QXBwbGljYXRpb25TaG91bGRIYW5kbGVSZW9wZW4hXCIsXG5cdFx0V2luZG93RGlkQmVjb21lS2V5OiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dEaWRCZWNvbWVNYWluOiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVNYWluXCIsXG5cdFx0V2luZG93RGlkQmVnaW5TaGVldDogXCJtYWM6V2luZG93RGlkQmVnaW5TaGVldFwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUFscGhhOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VBbHBoYVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUJhY2tpbmdMb2NhdGlvbjogXCJtYWM6V2luZG93RGlkQ2hhbmdlQmFja2luZ0xvY2F0aW9uXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQmFja2luZ1Byb3BlcnRpZXM6IFwibWFjOldpbmRvd0RpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOldpbmRvd0RpZENoYW5nZU9jY2x1c2lvblN0YXRlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW46IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2U6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2VQcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5TcGFjZVByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTaGFyaW5nVHlwZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2hhcmluZ1R5cGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUaXRsZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVGl0bGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUb29sYmFyOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VUb29sYmFyXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd0RpZERlbWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dEaWRFbmRTaGVldDogXCJtYWM6V2luZG93RGlkRW5kU2hlZXRcIixcblx0XHRXaW5kb3dEaWRFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd0RpZEVudGVyRnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dEaWRFeGl0RnVsbFNjcmVlbjogXCJtYWM6V2luZG93RGlkRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEV4aXRWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd0RpZEV4cG9zZTogXCJtYWM6V2luZG93RGlkRXhwb3NlXCIsXG5cdFx0V2luZG93RGlkRm9jdXM6IFwibWFjOldpbmRvd0RpZEZvY3VzXCIsXG5cdFx0V2luZG93RGlkTWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJtYWM6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRPcmRlck9mZlNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd0RpZE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dEaWRSZXNpZ25LZXk6IFwibWFjOldpbmRvd0RpZFJlc2lnbktleVwiLFxuXHRcdFdpbmRvd0RpZFJlc2lnbk1haW46IFwibWFjOldpbmRvd0RpZFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwibWFjOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZTogXCJtYWM6V2luZG93RGlkVXBkYXRlXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd0RpZFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRpdGxlOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVRvb2xiYXJcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5XCIsXG5cdFx0V2luZG93U2hvdWxkQ2xvc2U6IFwibWFjOldpbmRvd1Nob3VsZENsb3NlIVwiLFxuXHRcdFdpbmRvd1dpbGxCZWNvbWVLZXk6IFwibWFjOldpbmRvd1dpbGxCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dXaWxsQmVjb21lTWFpbjogXCJtYWM6V2luZG93V2lsbEJlY29tZU1haW5cIixcblx0XHRXaW5kb3dXaWxsQmVnaW5TaGVldDogXCJtYWM6V2luZG93V2lsbEJlZ2luU2hlZXRcIixcblx0XHRXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93V2lsbENsb3NlOiBcIm1hYzpXaW5kb3dXaWxsQ2xvc2VcIixcblx0XHRXaW5kb3dXaWxsRGVtaW5pYXR1cml6ZTogXCJtYWM6V2luZG93V2lsbERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd1dpbGxFbnRlclZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEV4aXRGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyOiBcIm1hYzpXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsRm9jdXNcIixcblx0XHRXaW5kb3dXaWxsTWluaWF0dXJpemU6IFwibWFjOldpbmRvd1dpbGxNaW5pYXR1cml6ZVwiLFxuXHRcdFdpbmRvd1dpbGxNb3ZlOiBcIm1hYzpXaW5kb3dXaWxsTW92ZVwiLFxuXHRcdFdpbmRvd1dpbGxPcmRlck9mZlNjcmVlbjogXCJtYWM6V2luZG93V2lsbE9yZGVyT2ZmU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd1dpbGxPcmRlck9uU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbFJlc2lnbk1haW46IFwibWFjOldpbmRvd1dpbGxSZXNpZ25NYWluXCIsXG5cdFx0V2luZG93V2lsbFJlc2l6ZTogXCJtYWM6V2luZG93V2lsbFJlc2l6ZVwiLFxuXHRcdFdpbmRvd1dpbGxVbmZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsVW5mb2N1c1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVBbHBoYVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3I6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXM6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllc1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVTaGFkb3dcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlVGl0bGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVUb29sYmFyOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVG9vbGJhclwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd1dpbGxVc2VTdGFuZGFyZEZyYW1lOiBcIm1hYzpXaW5kb3dXaWxsVXNlU3RhbmRhcmRGcmFtZVwiLFxuXHRcdE1lbnVXaWxsT3BlbjogXCJtYWM6TWVudVdpbGxPcGVuXCIsXG5cdFx0TWVudURpZE9wZW46IFwibWFjOk1lbnVEaWRPcGVuXCIsXG5cdFx0TWVudURpZENsb3NlOiBcIm1hYzpNZW51RGlkQ2xvc2VcIixcblx0XHRNZW51V2lsbFNlbmRBY3Rpb246IFwibWFjOk1lbnVXaWxsU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVXaWxsSGlnaGxpZ2h0SXRlbTogXCJtYWM6TWVudVdpbGxIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudURpZEhpZ2hsaWdodEl0ZW06IFwibWFjOk1lbnVEaWRIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudVdpbGxEaXNwbGF5SXRlbTogXCJtYWM6TWVudVdpbGxEaXNwbGF5SXRlbVwiLFxuXHRcdE1lbnVEaWREaXNwbGF5SXRlbTogXCJtYWM6TWVudURpZERpc3BsYXlJdGVtXCIsXG5cdFx0TWVudVdpbGxBZGRJdGVtOiBcIm1hYzpNZW51V2lsbEFkZEl0ZW1cIixcblx0XHRNZW51RGlkQWRkSXRlbTogXCJtYWM6TWVudURpZEFkZEl0ZW1cIixcblx0XHRNZW51V2lsbFJlbW92ZUl0ZW06IFwibWFjOk1lbnVXaWxsUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVEaWRSZW1vdmVJdGVtOiBcIm1hYzpNZW51RGlkUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVXaWxsQmVnaW5UcmFja2luZzogXCJtYWM6TWVudVdpbGxCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudURpZEJlZ2luVHJhY2tpbmc6IFwibWFjOk1lbnVEaWRCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxFbmRUcmFja2luZzogXCJtYWM6TWVudVdpbGxFbmRUcmFja2luZ1wiLFxuXHRcdE1lbnVEaWRFbmRUcmFja2luZzogXCJtYWM6TWVudURpZEVuZFRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxVcGRhdGU6IFwibWFjOk1lbnVXaWxsVXBkYXRlXCIsXG5cdFx0TWVudURpZFVwZGF0ZTogXCJtYWM6TWVudURpZFVwZGF0ZVwiLFxuXHRcdE1lbnVXaWxsUG9wVXA6IFwibWFjOk1lbnVXaWxsUG9wVXBcIixcblx0XHRNZW51RGlkUG9wVXA6IFwibWFjOk1lbnVEaWRQb3BVcFwiLFxuXHRcdE1lbnVXaWxsU2VuZEFjdGlvblRvSXRlbTogXCJtYWM6TWVudVdpbGxTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0TWVudURpZFNlbmRBY3Rpb25Ub0l0ZW06IFwibWFjOk1lbnVEaWRTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0V2ViVmlld0RpZFN0YXJ0UHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkU3RhcnRQcm92aXNpb25hbE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZENvbW1pdE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRDb21taXROYXZpZ2F0aW9uXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZFwiLFxuXHRcdFdpbmRvd0ZpbGVEcmFnZ2luZ1BlcmZvcm1lZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nUGVyZm9ybWVkXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRXhpdGVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdFeGl0ZWRcIixcblx0fSxcblx0TGludXg6IHtcblx0XHRTeXN0ZW1UaGVtZUNoYW5nZWQ6IFwibGludXg6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdH0sXG5cdENvbW1vbjoge1xuXHRcdEFwcGxpY2F0aW9uU3RhcnRlZDogXCJjb21tb246QXBwbGljYXRpb25TdGFydGVkXCIsXG5cdFx0V2luZG93TWF4aW1pc2U6IFwiY29tbW9uOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJjb21tb246V2luZG93VW5NYXhpbWlzZVwiLFxuXHRcdFdpbmRvd0Z1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd0Z1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dVbkZ1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwiY29tbW9uOldpbmRvd1Jlc3RvcmVcIixcblx0XHRXaW5kb3dNaW5pbWlzZTogXCJjb21tb246V2luZG93TWluaW1pc2VcIixcblx0XHRXaW5kb3dVbk1pbmltaXNlOiBcImNvbW1vbjpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2luZzogXCJjb21tb246V2luZG93Q2xvc2luZ1wiLFxuXHRcdFdpbmRvd1pvb206IFwiY29tbW9uOldpbmRvd1pvb21cIixcblx0XHRXaW5kb3dab29tSW46IFwiY29tbW9uOldpbmRvd1pvb21JblwiLFxuXHRcdFdpbmRvd1pvb21PdXQ6IFwiY29tbW9uOldpbmRvd1pvb21PdXRcIixcblx0XHRXaW5kb3dab29tUmVzZXQ6IFwiY29tbW9uOldpbmRvd1pvb21SZXNldFwiLFxuXHRcdFdpbmRvd0ZvY3VzOiBcImNvbW1vbjpXaW5kb3dGb2N1c1wiLFxuXHRcdFdpbmRvd0xvc3RGb2N1czogXCJjb21tb246V2luZG93TG9zdEZvY3VzXCIsXG5cdFx0V2luZG93U2hvdzogXCJjb21tb246V2luZG93U2hvd1wiLFxuXHRcdFdpbmRvd0hpZGU6IFwiY29tbW9uOldpbmRvd0hpZGVcIixcblx0XHRXaW5kb3dEUElDaGFuZ2VkOiBcImNvbW1vbjpXaW5kb3dEUElDaGFuZ2VkXCIsXG5cdFx0V2luZG93RmlsZXNEcm9wcGVkOiBcImNvbW1vbjpXaW5kb3dGaWxlc0Ryb3BwZWRcIixcblx0XHRXaW5kb3dSdW50aW1lUmVhZHk6IFwiY29tbW9uOldpbmRvd1J1bnRpbWVSZWFkeVwiLFxuXHRcdFRoZW1lQ2hhbmdlZDogXCJjb21tb246VGhlbWVDaGFuZ2VkXCIsXG5cdH0sXG59O1xuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcGVuRmlsZURpYWxvZ09wdGlvbnNcclxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ2hvb3NlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjaG9zZW4uXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZUZpbGVzXSAtIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DcmVhdGVEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNyZWF0ZWQuXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1Nob3dIaWRkZW5GaWxlc10gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGZpbGVzIHNob3VsZCBiZSBzaG93bi5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbUmVzb2x2ZXNBbGlhc2VzXSAtIEluZGljYXRlcyBpZiBhbGlhc2VzIHNob3VsZCBiZSByZXNvbHZlZC5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbQWxsb3dzTXVsdGlwbGVTZWxlY3Rpb25dIC0gSW5kaWNhdGVzIGlmIG11bHRpcGxlIHNlbGVjdGlvbiBpcyBhbGxvd2VkLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtIaWRlRXh0ZW5zaW9uXSAtIEluZGljYXRlcyBpZiB0aGUgZXh0ZW5zaW9uIHNob3VsZCBiZSBoaWRkZW4uXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhblNlbGVjdEhpZGRlbkV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGV4dGVuc2lvbnMgY2FuIGJlIHNlbGVjdGVkLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtUcmVhdHNGaWxlUGFja2FnZXNBc0RpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBmaWxlIHBhY2thZ2VzIHNob3VsZCBiZSB0cmVhdGVkIGFzIGRpcmVjdG9yaWVzLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtBbGxvd3NPdGhlckZpbGV0eXBlc10gLSBJbmRpY2F0ZXMgaWYgb3RoZXIgZmlsZSB0eXBlcyBhcmUgYWxsb3dlZC5cclxuICogQHByb3BlcnR5IHtGaWxlRmlsdGVyW119IFtGaWx0ZXJzXSAtIEFycmF5IG9mIGZpbGUgZmlsdGVycy5cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtUaXRsZV0gLSBUaXRsZSBvZiB0aGUgZGlhbG9nLlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW01lc3NhZ2VdIC0gTWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbQnV0dG9uVGV4dF0gLSBUZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi5cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtEaXJlY3RvcnldIC0gRGlyZWN0b3J5IHRvIG9wZW4gaW4gdGhlIGRpYWxvZy5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbRGV0YWNoZWRdIC0gSW5kaWNhdGVzIGlmIHRoZSBkaWFsb2cgc2hvdWxkIGFwcGVhciBkZXRhY2hlZCBmcm9tIHRoZSBtYWluIHdpbmRvdy5cclxuICovXHJcblxyXG5cclxuLyoqXHJcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNhdmVGaWxlRGlhbG9nT3B0aW9uc1xyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0ZpbGVuYW1lXSAtIERlZmF1bHQgZmlsZW5hbWUgdG8gdXNlIGluIHRoZSBkaWFsb2cuXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZURpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBkaXJlY3RvcmllcyBjYW4gYmUgY2hvc2VuLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DaG9vc2VGaWxlc10gLSBJbmRpY2F0ZXMgaWYgZmlsZXMgY2FuIGJlIGNob3Nlbi5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ3JlYXRlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtTaG93SGlkZGVuRmlsZXNdIC0gSW5kaWNhdGVzIGlmIGhpZGRlbiBmaWxlcyBzaG91bGQgYmUgc2hvd24uXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1Jlc29sdmVzQWxpYXNlc10gLSBJbmRpY2F0ZXMgaWYgYWxpYXNlcyBzaG91bGQgYmUgcmVzb2x2ZWQuXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c011bHRpcGxlU2VsZWN0aW9uXSAtIEluZGljYXRlcyBpZiBtdWx0aXBsZSBzZWxlY3Rpb24gaXMgYWxsb3dlZC5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbSGlkZUV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgdGhlIGV4dGVuc2lvbiBzaG91bGQgYmUgaGlkZGVuLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5TZWxlY3RIaWRkZW5FeHRlbnNpb25dIC0gSW5kaWNhdGVzIGlmIGhpZGRlbiBleHRlbnNpb25zIGNhbiBiZSBzZWxlY3RlZC5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZmlsZSBwYWNrYWdlcyBzaG91bGQgYmUgdHJlYXRlZCBhcyBkaXJlY3Rvcmllcy5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbQWxsb3dzT3RoZXJGaWxldHlwZXNdIC0gSW5kaWNhdGVzIGlmIG90aGVyIGZpbGUgdHlwZXMgYXJlIGFsbG93ZWQuXHJcbiAqIEBwcm9wZXJ0eSB7RmlsZUZpbHRlcltdfSBbRmlsdGVyc10gLSBBcnJheSBvZiBmaWxlIGZpbHRlcnMuXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGl0bGUgb2YgdGhlIGRpYWxvZy5cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtNZXNzYWdlXSAtIE1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0J1dHRvblRleHRdIC0gVGV4dCB0byBkaXNwbGF5IG9uIHRoZSBidXR0b24uXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRGlyZWN0b3J5XSAtIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0RldGFjaGVkXSAtIEluZGljYXRlcyBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cuXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE1lc3NhZ2VEaWFsb2dPcHRpb25zXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGhlIHRpdGxlIG9mIHRoZSBkaWFsb2cgd2luZG93LlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW01lc3NhZ2VdIC0gVGhlIG1haW4gbWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuXHJcbiAqIEBwcm9wZXJ0eSB7QnV0dG9uW119IFtCdXR0b25zXSAtIEFycmF5IG9mIGJ1dHRvbiBvcHRpb25zIHRvIHNob3cgaW4gdGhlIGRpYWxvZy5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbRGV0YWNoZWRdIC0gVHJ1ZSBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cgKGlmIGFwcGxpY2FibGUpLlxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBCdXR0b25cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtMYWJlbF0gLSBUZXh0IHRoYXQgYXBwZWFycyB3aXRoaW4gdGhlIGJ1dHRvbi5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbSXNDYW5jZWxdIC0gVHJ1ZSBpZiB0aGUgYnV0dG9uIHNob3VsZCBjYW5jZWwgYW4gb3BlcmF0aW9uIHdoZW4gY2xpY2tlZC5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbSXNEZWZhdWx0XSAtIFRydWUgaWYgdGhlIGJ1dHRvbiBzaG91bGQgYmUgdGhlIGRlZmF1bHQgYWN0aW9uIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyBlbnRlci5cclxuICovXHJcblxyXG4vKipcclxuICogQHR5cGVkZWYge09iamVjdH0gRmlsZUZpbHRlclxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0Rpc3BsYXlOYW1lXSAtIERpc3BsYXkgbmFtZSBmb3IgdGhlIGZpbHRlciwgaXQgY291bGQgYmUgXCJUZXh0IEZpbGVzXCIsIFwiSW1hZ2VzXCIgZXRjLlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW1BhdHRlcm5dIC0gUGF0dGVybiB0byBtYXRjaCBmb3IgdGhlIGZpbHRlciwgZS5nLiBcIioudHh0OyoubWRcIiBmb3IgdGV4dCBtYXJrZG93biBmaWxlcy5cclxuICovXHJcblxyXG4vLyBzZXR1cFxyXG53aW5kb3cuX3dhaWxzID0gd2luZG93Ll93YWlscyB8fCB7fTtcclxud2luZG93Ll93YWlscy5kaWFsb2dFcnJvckNhbGxiYWNrID0gZGlhbG9nRXJyb3JDYWxsYmFjaztcclxud2luZG93Ll93YWlscy5kaWFsb2dSZXN1bHRDYWxsYmFjayA9IGRpYWxvZ1Jlc3VsdENhbGxiYWNrO1xyXG5cclxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xyXG5cclxuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSAnbmFub2lkL25vbi1zZWN1cmUnO1xyXG5cclxuLy8gRGVmaW5lIGNvbnN0YW50cyBmcm9tIHRoZSBgbWV0aG9kc2Agb2JqZWN0IGluIFRpdGxlIENhc2VcclxuY29uc3QgRGlhbG9nSW5mbyA9IDA7XHJcbmNvbnN0IERpYWxvZ1dhcm5pbmcgPSAxO1xyXG5jb25zdCBEaWFsb2dFcnJvciA9IDI7XHJcbmNvbnN0IERpYWxvZ1F1ZXN0aW9uID0gMztcclxuY29uc3QgRGlhbG9nT3BlbkZpbGUgPSA0O1xyXG5jb25zdCBEaWFsb2dTYXZlRmlsZSA9IDU7XHJcblxyXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5EaWFsb2csICcnKTtcclxuY29uc3QgZGlhbG9nUmVzcG9uc2VzID0gbmV3IE1hcCgpO1xyXG5cclxuLyoqXHJcbiAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBpZCB0aGF0IGlzIG5vdCBwcmVzZW50IGluIGRpYWxvZ1Jlc3BvbnNlcy5cclxuICogQHJldHVybnMge3N0cmluZ30gdW5pcXVlIGlkXHJcbiAqL1xyXG5mdW5jdGlvbiBnZW5lcmF0ZUlEKCkge1xyXG4gICAgbGV0IHJlc3VsdDtcclxuICAgIGRvIHtcclxuICAgICAgICByZXN1bHQgPSBuYW5vaWQoKTtcclxuICAgIH0gd2hpbGUgKGRpYWxvZ1Jlc3BvbnNlcy5oYXMocmVzdWx0KSk7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG4vKipcclxuICogU2hvd3MgYSBkaWFsb2cgb2Ygc3BlY2lmaWVkIHR5cGUgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHR5cGUgLSB0eXBlIG9mIGRpYWxvZ1xyXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfE9wZW5GaWxlRGlhbG9nT3B0aW9uc3xTYXZlRmlsZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBvcHRpb25zIGZvciB0aGUgZGlhbG9nXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlfSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCByZXN1bHQgb2YgZGlhbG9nXHJcbiAqL1xyXG5mdW5jdGlvbiBkaWFsb2codHlwZSwgb3B0aW9ucyA9IHt9KSB7XHJcbiAgICBjb25zdCBpZCA9IGdlbmVyYXRlSUQoKTtcclxuICAgIG9wdGlvbnNbXCJkaWFsb2ctaWRcIl0gPSBpZDtcclxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgZGlhbG9nUmVzcG9uc2VzLnNldChpZCwge3Jlc29sdmUsIHJlamVjdH0pO1xyXG4gICAgICAgIGNhbGwodHlwZSwgb3B0aW9ucykuY2F0Y2goKGVycm9yKSA9PiB7XHJcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XHJcbiAgICAgICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5kZWxldGUoaWQpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBIYW5kbGVzIHRoZSBjYWxsYmFjayBmcm9tIGEgZGlhbG9nLlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBUaGUgSUQgb2YgdGhlIGRpYWxvZyByZXNwb25zZS5cclxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgLSBUaGUgZGF0YSByZWNlaXZlZCBmcm9tIHRoZSBkaWFsb2cuXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNKU09OIC0gRmxhZyBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIGRhdGEgaXMgaW4gSlNPTiBmb3JtYXQuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cclxuICovXHJcbmZ1bmN0aW9uIGRpYWxvZ1Jlc3VsdENhbGxiYWNrKGlkLCBkYXRhLCBpc0pTT04pIHtcclxuICAgIGxldCBwID0gZGlhbG9nUmVzcG9uc2VzLmdldChpZCk7XHJcbiAgICBpZiAocCkge1xyXG4gICAgICAgIGlmIChpc0pTT04pIHtcclxuICAgICAgICAgICAgcC5yZXNvbHZlKEpTT04ucGFyc2UoZGF0YSkpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHAucmVzb2x2ZShkYXRhKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZGlhbG9nUmVzcG9uc2VzLmRlbGV0ZShpZCk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDYWxsYmFjayBmdW5jdGlvbiBmb3IgaGFuZGxpbmcgZXJyb3JzIGluIGRpYWxvZy5cclxuICpcclxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSBkaWFsb2cgcmVzcG9uc2UuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3ZvaWR9XHJcbiAqL1xyXG5mdW5jdGlvbiBkaWFsb2dFcnJvckNhbGxiYWNrKGlkLCBtZXNzYWdlKSB7XHJcbiAgICBsZXQgcCA9IGRpYWxvZ1Jlc3BvbnNlcy5nZXQoaWQpO1xyXG4gICAgaWYgKHApIHtcclxuICAgICAgICBwLnJlamVjdChtZXNzYWdlKTtcclxuICAgICAgICBkaWFsb2dSZXNwb25zZXMuZGVsZXRlKGlkKTtcclxuICAgIH1cclxufVxyXG5cclxuXHJcbi8vIFJlcGxhY2UgYG1ldGhvZHNgIHdpdGggY29uc3RhbnRzIGluIFRpdGxlIENhc2VcclxuXHJcbi8qKlxyXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcclxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gLSBUaGUgbGFiZWwgb2YgdGhlIGJ1dHRvbiBwcmVzc2VkXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgSW5mbyA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nSW5mbywgb3B0aW9ucyk7XHJcblxyXG4vKipcclxuICogQHBhcmFtIHtNZXNzYWdlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gVGhlIGxhYmVsIG9mIHRoZSBidXR0b24gcHJlc3NlZFxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IFdhcm5pbmcgPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ1dhcm5pbmcsIG9wdGlvbnMpO1xyXG5cclxuLyoqXHJcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcclxuICovXHJcbmV4cG9ydCBjb25zdCBFcnJvciA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nRXJyb3IsIG9wdGlvbnMpO1xyXG5cclxuLyoqXHJcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcclxuICovXHJcbmV4cG9ydCBjb25zdCBRdWVzdGlvbiA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nUXVlc3Rpb24sIG9wdGlvbnMpO1xyXG5cclxuLyoqXHJcbiAqIEBwYXJhbSB7T3BlbkZpbGVEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcclxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nW118c3RyaW5nPn0gUmV0dXJucyBzZWxlY3RlZCBmaWxlIG9yIGxpc3Qgb2YgZmlsZXMuIFJldHVybnMgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaXMgc2VsZWN0ZWQuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgT3BlbkZpbGUgPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ09wZW5GaWxlLCBvcHRpb25zKTtcclxuXHJcbi8qKlxyXG4gKiBAcGFyYW0ge1NhdmVGaWxlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IFJldHVybnMgdGhlIHNlbGVjdGVkIGZpbGUuIFJldHVybnMgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaXMgc2VsZWN0ZWQuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgU2F2ZUZpbGUgPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ1NhdmVGaWxlLCBvcHRpb25zKTtcclxuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuaW1wb3J0IHsgbmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXMgfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZC9ub24tc2VjdXJlJztcclxuXHJcbi8vIFNldHVwXHJcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xyXG53aW5kb3cuX3dhaWxzLmNhbGxSZXN1bHRIYW5kbGVyID0gcmVzdWx0SGFuZGxlcjtcclxud2luZG93Ll93YWlscy5jYWxsRXJyb3JIYW5kbGVyID0gZXJyb3JIYW5kbGVyO1xyXG5cclxuXHJcbmNvbnN0IENhbGxCaW5kaW5nID0gMDtcclxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ2FsbCwgJycpO1xyXG5sZXQgY2FsbFJlc3BvbnNlcyA9IG5ldyBNYXAoKTtcclxuXHJcbi8qKlxyXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgSUQgdXNpbmcgdGhlIG5hbm9pZCBsaWJyYXJ5LlxyXG4gKlxyXG4gKiBAcmV0dXJuIHtzdHJpbmd9IC0gQSB1bmlxdWUgSUQgdGhhdCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgY2FsbFJlc3BvbnNlcyBzZXQuXHJcbiAqL1xyXG5mdW5jdGlvbiBnZW5lcmF0ZUlEKCkge1xyXG4gICAgbGV0IHJlc3VsdDtcclxuICAgIGRvIHtcclxuICAgICAgICByZXN1bHQgPSBuYW5vaWQoKTtcclxuICAgIH0gd2hpbGUgKGNhbGxSZXNwb25zZXMuaGFzKHJlc3VsdCkpO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuLyoqXHJcbiAqIEhhbmRsZXMgdGhlIHJlc3VsdCBvZiBhIGNhbGwgcmVxdWVzdC5cclxuICpcclxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSByZXF1ZXN0IHRvIGhhbmRsZSB0aGUgcmVzdWx0IGZvci5cclxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgLSBUaGUgcmVzdWx0IGRhdGEgb2YgdGhlIHJlcXVlc3QuXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNKU09OIC0gSW5kaWNhdGVzIHdoZXRoZXIgdGhlIGRhdGEgaXMgSlNPTiBvciBub3QuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3VuZGVmaW5lZH0gLSBUaGlzIG1ldGhvZCBkb2VzIG5vdCByZXR1cm4gYW55IHZhbHVlLlxyXG4gKi9cclxuZnVuY3Rpb24gcmVzdWx0SGFuZGxlcihpZCwgZGF0YSwgaXNKU09OKSB7XHJcbiAgICBjb25zdCBwcm9taXNlSGFuZGxlciA9IGdldEFuZERlbGV0ZVJlc3BvbnNlKGlkKTtcclxuICAgIGlmIChwcm9taXNlSGFuZGxlcikge1xyXG4gICAgICAgIHByb21pc2VIYW5kbGVyLnJlc29sdmUoaXNKU09OID8gSlNPTi5wYXJzZShkYXRhKSA6IGRhdGEpO1xyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogSGFuZGxlcyB0aGUgZXJyb3IgZnJvbSBhIGNhbGwgcmVxdWVzdC5cclxuICpcclxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSBwcm9taXNlIGhhbmRsZXIuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UgdG8gcmVqZWN0IHRoZSBwcm9taXNlIGhhbmRsZXIgd2l0aC5cclxuICpcclxuICogQHJldHVybiB7dm9pZH1cclxuICovXHJcbmZ1bmN0aW9uIGVycm9ySGFuZGxlcihpZCwgbWVzc2FnZSkge1xyXG4gICAgY29uc3QgcHJvbWlzZUhhbmRsZXIgPSBnZXRBbmREZWxldGVSZXNwb25zZShpZCk7XHJcbiAgICBpZiAocHJvbWlzZUhhbmRsZXIpIHtcclxuICAgICAgICBwcm9taXNlSGFuZGxlci5yZWplY3QobWVzc2FnZSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXRyaWV2ZXMgYW5kIHJlbW92ZXMgdGhlIHJlc3BvbnNlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gSUQgZnJvbSB0aGUgY2FsbFJlc3BvbnNlcyBtYXAuXHJcbiAqXHJcbiAqIEBwYXJhbSB7YW55fSBpZCAtIFRoZSBJRCBvZiB0aGUgcmVzcG9uc2UgdG8gYmUgcmV0cmlldmVkIGFuZCByZW1vdmVkLlxyXG4gKlxyXG4gKiBAcmV0dXJucyB7YW55fSBUaGUgcmVzcG9uc2Ugb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gSUQuXHJcbiAqL1xyXG5mdW5jdGlvbiBnZXRBbmREZWxldGVSZXNwb25zZShpZCkge1xyXG4gICAgY29uc3QgcmVzcG9uc2UgPSBjYWxsUmVzcG9uc2VzLmdldChpZCk7XHJcbiAgICBjYWxsUmVzcG9uc2VzLmRlbGV0ZShpZCk7XHJcbiAgICByZXR1cm4gcmVzcG9uc2U7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFeGVjdXRlcyBhIGNhbGwgdXNpbmcgdGhlIHByb3ZpZGVkIHR5cGUgYW5kIG9wdGlvbnMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gdHlwZSAtIFRoZSB0eXBlIG9mIGNhbGwgdG8gZXhlY3V0ZS5cclxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSAtIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIGNhbGwuXHJcbiAqIEByZXR1cm4ge1Byb21pc2V9IC0gQSBwcm9taXNlIHRoYXQgd2lsbCBiZSByZXNvbHZlZCBvciByZWplY3RlZCBiYXNlZCBvbiB0aGUgcmVzdWx0IG9mIHRoZSBjYWxsLlxyXG4gKi9cclxuZnVuY3Rpb24gY2FsbEJpbmRpbmcodHlwZSwgb3B0aW9ucyA9IHt9KSB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IGlkID0gZ2VuZXJhdGVJRCgpO1xyXG4gICAgICAgIG9wdGlvbnNbXCJjYWxsLWlkXCJdID0gaWQ7XHJcbiAgICAgICAgY2FsbFJlc3BvbnNlcy5zZXQoaWQsIHsgcmVzb2x2ZSwgcmVqZWN0IH0pO1xyXG4gICAgICAgIGNhbGwodHlwZSwgb3B0aW9ucykuY2F0Y2goKGVycm9yKSA9PiB7XHJcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XHJcbiAgICAgICAgICAgIGNhbGxSZXNwb25zZXMuZGVsZXRlKGlkKTtcclxuICAgICAgICB9KTtcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogQ2FsbCBtZXRob2QuXHJcbiAqXHJcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgZm9yIHRoZSBtZXRob2QuXHJcbiAqIEByZXR1cm5zIHtPYmplY3R9IC0gVGhlIHJlc3VsdCBvZiB0aGUgY2FsbC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBDYWxsKG9wdGlvbnMpIHtcclxuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywgb3B0aW9ucyk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFeGVjdXRlcyBhIG1ldGhvZCBieSBuYW1lLlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgaW4gdGhlIGZvcm1hdCAncGFja2FnZS5zdHJ1Y3QubWV0aG9kJy5cclxuICogQHBhcmFtIHsuLi4qfSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXHJcbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgbmFtZSBpcyBub3QgYSBzdHJpbmcgb3IgaXMgbm90IGluIHRoZSBjb3JyZWN0IGZvcm1hdC5cclxuICogQHJldHVybnMgeyp9IFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBleGVjdXRpb24uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gQnlOYW1lKG5hbWUsIC4uLmFyZ3MpIHtcclxuICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gXCJzdHJpbmdcIiB8fCBuYW1lLnNwbGl0KFwiLlwiKS5sZW5ndGggIT09IDMpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYWxsQnlOYW1lIHJlcXVpcmVzIGEgc3RyaW5nIGluIHRoZSBmb3JtYXQgJ3BhY2thZ2Uuc3RydWN0Lm1ldGhvZCdcIik7XHJcbiAgICB9XHJcbiAgICBsZXQgW3BhY2thZ2VOYW1lLCBzdHJ1Y3ROYW1lLCBtZXRob2ROYW1lXSA9IG5hbWUuc3BsaXQoXCIuXCIpO1xyXG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XHJcbiAgICAgICAgcGFja2FnZU5hbWUsXHJcbiAgICAgICAgc3RydWN0TmFtZSxcclxuICAgICAgICBtZXRob2ROYW1lLFxyXG4gICAgICAgIGFyZ3NcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogQ2FsbHMgYSBtZXRob2QgYnkgaXRzIElEIHdpdGggdGhlIHNwZWNpZmllZCBhcmd1bWVudHMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBtZXRob2RJRCAtIFRoZSBJRCBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXHJcbiAqIEBwYXJhbSB7Li4uKn0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxyXG4gKiBAcmV0dXJuIHsqfSAtIFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBjYWxsLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEJ5SUQobWV0aG9kSUQsIC4uLmFyZ3MpIHtcclxuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywge1xyXG4gICAgICAgIG1ldGhvZElELFxyXG4gICAgICAgIGFyZ3NcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogQ2FsbHMgYSBtZXRob2Qgb24gYSBwbHVnaW4uXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBwbHVnaW5OYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHBsdWdpbi5cclxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXHJcbiAqIEBwYXJhbSB7Li4uKn0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxyXG4gKiBAcmV0dXJucyB7Kn0gLSBUaGUgcmVzdWx0IG9mIHRoZSBtZXRob2QgY2FsbC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBQbHVnaW4ocGx1Z2luTmFtZSwgbWV0aG9kTmFtZSwgLi4uYXJncykge1xyXG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XHJcbiAgICAgICAgcGFja2FnZU5hbWU6IFwid2FpbHMtcGx1Z2luc1wiLFxyXG4gICAgICAgIHN0cnVjdE5hbWU6IHBsdWdpbk5hbWUsXHJcbiAgICAgICAgbWV0aG9kTmFtZSxcclxuICAgICAgICBhcmdzXHJcbiAgICB9KTtcclxufVxyXG4iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuaW1wb3J0IHtkZWJ1Z0xvZ30gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZ1wiO1xyXG5cclxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XHJcblxyXG5pbXBvcnQgKiBhcyBBcHBsaWNhdGlvbiBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb25cIjtcclxuaW1wb3J0ICogYXMgQnJvd3NlciBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvYnJvd3NlclwiO1xyXG5pbXBvcnQgKiBhcyBDbGlwYm9hcmQgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZFwiO1xyXG5pbXBvcnQgKiBhcyBDb250ZXh0TWVudSBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvY29udGV4dG1lbnVcIjtcclxuaW1wb3J0ICogYXMgRHJhZyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZHJhZ1wiO1xyXG5pbXBvcnQgKiBhcyBGbGFncyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3NcIjtcclxuaW1wb3J0ICogYXMgU2NyZWVucyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvc2NyZWVuc1wiO1xyXG5pbXBvcnQgKiBhcyBTeXN0ZW0gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbVwiO1xyXG5pbXBvcnQgKiBhcyBXaW5kb3cgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dpbmRvd1wiO1xyXG5pbXBvcnQgKiBhcyBXTUwgZnJvbSAnLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvd21sJztcclxuaW1wb3J0ICogYXMgRXZlbnRzIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9ldmVudHNcIjtcclxuaW1wb3J0ICogYXMgRGlhbG9ncyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZGlhbG9nc1wiO1xyXG5pbXBvcnQgKiBhcyBDYWxsIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxsc1wiO1xyXG5pbXBvcnQge2ludm9rZX0gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbVwiO1xyXG5cclxuLyoqKlxyXG4gVGhpcyB0ZWNobmlxdWUgZm9yIHByb3BlciBsb2FkIGRldGVjdGlvbiBpcyB0YWtlbiBmcm9tIEhUTVg6XHJcblxyXG4gQlNEIDItQ2xhdXNlIExpY2Vuc2VcclxuXHJcbiBDb3B5cmlnaHQgKGMpIDIwMjAsIEJpZyBTa3kgU29mdHdhcmVcclxuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcblxyXG4gUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0XHJcbiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcclxuXHJcbiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcclxuIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxyXG5cclxuIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcclxuIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cclxuIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxyXG5cclxuIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiXHJcbiBBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFXHJcbiBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcclxuIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEVcclxuIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMXHJcbiBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUlxyXG4gU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVJcclxuIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksXHJcbiBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRVxyXG4gT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cclxuXHJcbiAqKiovXHJcblxyXG53aW5kb3cuX3dhaWxzLmludm9rZT1pbnZva2U7XHJcblxyXG53aW5kb3cud2FpbHMgPSB3aW5kb3cud2FpbHMgfHwge307XHJcbndpbmRvdy53YWlscy5BcHBsaWNhdGlvbiA9IEFwcGxpY2F0aW9uO1xyXG53aW5kb3cud2FpbHMuQnJvd3NlciA9IEJyb3dzZXI7XHJcbndpbmRvdy53YWlscy5DYWxsID0gQ2FsbDtcclxud2luZG93LndhaWxzLkNsaXBib2FyZCA9IENsaXBib2FyZDtcclxud2luZG93LndhaWxzLkRpYWxvZ3MgPSBEaWFsb2dzO1xyXG53aW5kb3cud2FpbHMuRXZlbnRzID0gRXZlbnRzO1xyXG53aW5kb3cud2FpbHMuRmxhZ3MgPSBGbGFncztcclxud2luZG93LndhaWxzLlNjcmVlbnMgPSBTY3JlZW5zO1xyXG53aW5kb3cud2FpbHMuU3lzdGVtID0gU3lzdGVtO1xyXG53aW5kb3cud2FpbHMuV2luZG93ID0gV2luZG93O1xyXG53aW5kb3cud2FpbHMuV01MID0gV01MO1xyXG5cclxuXHJcbmxldCBpc1JlYWR5ID0gZmFsc2VcclxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGZ1bmN0aW9uKCkge1xyXG4gICAgaXNSZWFkeSA9IHRydWVcclxuICAgIHdpbmRvdy5fd2FpbHMuaW52b2tlKCd3YWlsczpydW50aW1lOnJlYWR5Jyk7XHJcbiAgICBpZihERUJVRykge1xyXG4gICAgICAgIGRlYnVnTG9nKFwiV2FpbHMgUnVudGltZSBMb2FkZWRcIik7XHJcbiAgICB9XHJcbn0pXHJcblxyXG5mdW5jdGlvbiB3aGVuUmVhZHkoZm4pIHtcclxuICAgIGlmIChpc1JlYWR5IHx8IGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdjb21wbGV0ZScpIHtcclxuICAgICAgICBmbigpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZm4pO1xyXG4gICAgfVxyXG59XHJcblxyXG53aGVuUmVhZHkoKCkgPT4ge1xyXG4gICAgV01MLlJlbG9hZCgpO1xyXG59KTtcclxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7QUFLTyxXQUFTLFNBQVMsU0FBUztBQUU5QixZQUFRO0FBQUEsTUFDSixrQkFBa0IsVUFBVTtBQUFBLE1BQzVCO0FBQUEsTUFDQTtBQUFBLElBQ0o7QUFBQSxFQUNKOzs7QUNaQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7OztBQ0FBLE1BQUksY0FDRjtBQVdLLE1BQUksU0FBUyxDQUFDQSxRQUFPLE9BQU87QUFDakMsUUFBSSxLQUFLO0FBQ1QsUUFBSSxJQUFJQTtBQUNSLFdBQU8sS0FBSztBQUNWLFlBQU0sWUFBYSxLQUFLLE9BQU8sSUFBSSxLQUFNLENBQUM7QUFBQSxJQUM1QztBQUNBLFdBQU87QUFBQSxFQUNUOzs7QUNOQSxNQUFNLGFBQWEsT0FBTyxTQUFTLFNBQVM7QUFHckMsTUFBTSxjQUFjO0FBQUEsSUFDdkIsTUFBTTtBQUFBLElBQ04sV0FBVztBQUFBLElBQ1gsYUFBYTtBQUFBLElBQ2IsUUFBUTtBQUFBLElBQ1IsYUFBYTtBQUFBLElBQ2IsUUFBUTtBQUFBLElBQ1IsUUFBUTtBQUFBLElBQ1IsU0FBUztBQUFBLElBQ1QsUUFBUTtBQUFBLElBQ1IsU0FBUztBQUFBLEVBQ2I7QUFDTyxNQUFJLFdBQVcsT0FBTztBQXNCdEIsV0FBUyx1QkFBdUIsUUFBUSxZQUFZO0FBQ3ZELFdBQU8sU0FBVSxRQUFRLE9BQUssTUFBTTtBQUNoQyxhQUFPLGtCQUFrQixRQUFRLFFBQVEsWUFBWSxJQUFJO0FBQUEsSUFDN0Q7QUFBQSxFQUNKO0FBcUNBLFdBQVMsa0JBQWtCLFVBQVUsUUFBUSxZQUFZLE1BQU07QUFDM0QsUUFBSSxNQUFNLElBQUksSUFBSSxVQUFVO0FBQzVCLFFBQUksYUFBYSxPQUFPLFVBQVUsUUFBUTtBQUMxQyxRQUFJLGFBQWEsT0FBTyxVQUFVLE1BQU07QUFDeEMs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b0U7QUFBQSxJQUN4RjtBQUNBLFFBQUksQ0FBQyxhQUFhLFlBQVksVUFBVSxJQUFJLEtBQUssTUFBTSxHQUFHO0FBQzFELFdBQU8sWUFBWSxhQUFhO0FBQUEsTUFDNUI7QUFBQSxNQUNBO0FBQUEsTUFDQTtBQUFBLE1BQ0E7QUFBQSxJQUNKLENBQUM7QUFBQSxFQUNMO0FBU08sV0FBUyxLQUFLLGFBQWEsTUFBTTtBQUNwQyxXQUFPLFlBQVksYUFBYTtBQUFBLE1BQzVCO0FBQUEsTUFDQTtBQUFBLElBQ0osQ0FBQztBQUFBLEVBQ0w7QUFVTyxXQUFTLE9BQU8sWUFBWSxlQUFlLE1BQU07QUFDcEQsV0FBTyxZQUFZLGFBQWE7QUFBQSxNQUM1QixhQUFhO0FBQUEsTUFDYixZQUFZO0FBQUEsTUFDWjtBQUFBLE1BQ0E7QUFBQSxJQUNKLENBQUM7QUFBQSxFQUNMOzs7QUNwSkEsU0FBTyxTQUFTLE9BQU8sVUFBVSxDQUFDO0FBZ0RsQyxTQUFPLE9BQU8sU0FBTztBQUVyQixTQUFPLFFBQVEsT0FBTyxTQUFTLENBQUM7QUFDaEMsU0FBTyxNQUFNLGNBQWM7QUFDM0IsU0FBTyxNQUFNLFVBQVU7QUFDdkIsU0FBTyxNQUFNLE9BQU87QUFDcEIsU0FBTyxNQUFNLFlBQVk7QUFDekIsU0FBTyxNQUFNLFVBQVU7QUFDdkIsU0FBTyxNQUFNLFNBQVM7QUFDdEIsU0FBTyxNQUFNLFFBQVE7QUFDckIsU0FBTyxNQUFNLFVBQVU7QUFDdkIsU0FBTyxNQUFNLFNBQVM7QUFDdEIsU0FBTyxNQUFNLFNBQVM7QUFDdEIsU0FBTyxNQUFNLE1BQU07QUFHbkIsTUFBSSxVQUFVO0FBQ2QsV0FBUyxpQkFBaUIsb0JBQW9CLFdBQVc7QUFDckQsY0FBVTtBQUNWLFdBQU8sT0FBTyxPQUFPLHFCQUFxQjtBQUMxQyxRQUFHLE1BQU87QUFDTixlQUFTLHNCQUFzQjtBQUFBLElBQ25DO0FBQUEsRUFDSixDQUFDO0FBRUQsV0FBUyxVQUFVLElBQUk7QUFDbkIsUUFBSSxXQUFXLFNBQVMsZUFBZSxZQUFZO0FBQy9DLFNBQUc7QUFBQSxJQUNQLE9BQU87QUFDSCxlQUFTLGlCQUFpQixvQkFBb0IsRUFBRTtBQUFBLElBQ3BEO0FBQUEsRUFDSjtBQUVBLFlBQVUsTUFBTTtBQUNaLElBQUksT0FBTztBQUFBLEVBQ2YsQ0FBQzsiLAogICJuYW1lcyI6IFsic2l6ZSIsICJjYWxsIiwgImNhbGwiLCAiY2FsbCIsICJjYWxsIiwgImNhbGwiLCAiSGlkZSIsICJTaG93IiwgInNldFJlc2l6YWJsZSIsICJjYWxsIiwgIndpZHRoIiwgImhlaWdodCIsICJyZXNpemFibGUiLCAiSGlkZSIsICJTaG93IiwgImNhbGwiLCAiZXZlbnROYW1lIiwgIkVycm9yIiwgImNhbGwiLCAiRXJyb3IiLCAiY2FsbCIsICJnZW5lcmF0ZUlEIl0KfQo= +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb24uanMiLCAiLi4vLi4vLi4vcnVudGltZS9ub2RlX21vZHVsZXMvbmFub2lkL25vbi1zZWN1cmUvaW5kZXguanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3J1bnRpbWUuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXIuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZC5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvc3lzdGVtLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jb250ZXh0bWVudS5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3MuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RyYWcuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3NjcmVlbnMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dpbmRvdy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvd21sLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9ldmVudHMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50X3R5cGVzLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9kaWFsb2dzLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxscy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvY29tcGlsZWQvbWFpbi5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBMb2dzIGEgbWVzc2FnZSB0byB0aGUgY29uc29sZSB3aXRoIGN1c3RvbSBmb3JtYXR0aW5nLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVidWdMb2cobWVzc2FnZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAnJWMgd2FpbHMzICVjICcgKyBtZXNzYWdlICsgJyAnLFxuICAgICAgICAnYmFja2dyb3VuZDogI2FhMDAwMDsgY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDNweCAwcHggMHB4IDNweDsgcGFkZGluZzogMXB4OyBmb250LXNpemU6IDAuN3JlbScsXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjMDA5OTAwOyBjb2xvcjogI2ZmZjsgYm9yZGVyLXJhZGl1czogMHB4IDNweCAzcHggMHB4OyBwYWRkaW5nOiAxcHg7IGZvbnQtc2l6ZTogMC43cmVtJ1xuICAgICk7XG59IiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZVwiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQXBwbGljYXRpb24sICcnKTtcblxuY29uc3QgSGlkZU1ldGhvZCA9IDA7XG5jb25zdCBTaG93TWV0aG9kID0gMTtcbmNvbnN0IFF1aXRNZXRob2QgPSAyO1xuXG4vKipcbiAqIEhpZGVzIGEgY2VydGFpbiBtZXRob2QgYnkgY2FsbGluZyB0aGUgSGlkZU1ldGhvZCBmdW5jdGlvbi5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XG4gICAgcmV0dXJuIGNhbGwoSGlkZU1ldGhvZCk7XG59XG5cbi8qKlxuICogQ2FsbHMgdGhlIFNob3dNZXRob2QgYW5kIHJldHVybnMgdGhlIHJlc3VsdC5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpIHtcbiAgICByZXR1cm4gY2FsbChTaG93TWV0aG9kKTtcbn1cblxuLyoqXG4gKiBDYWxscyB0aGUgUXVpdE1ldGhvZCB0byB0ZXJtaW5hdGUgdGhlIHByb2dyYW0uXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFF1aXQoKSB7XG4gICAgcmV0dXJuIGNhbGwoUXVpdE1ldGhvZCk7XG59XG4iLCAibGV0IHVybEFscGhhYmV0ID1cbiAgJ3VzZWFuZG9tLTI2VDE5ODM0MFBYNzVweEpBQ0tWRVJZTUlOREJVU0hXT0xGX0dRWmJmZ2hqa2xxdnd5enJpY3QnXG5leHBvcnQgbGV0IGN1c3RvbUFscGhhYmV0ID0gKGFscGhhYmV0LCBkZWZhdWx0U2l6ZSA9IDIxKSA9PiB7XG4gIHJldHVybiAoc2l6ZSA9IGRlZmF1bHRTaXplKSA9PiB7XG4gICAgbGV0IGlkID0gJydcbiAgICBsZXQgaSA9IHNpemVcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICBpZCArPSBhbHBoYWJldFsoTWF0aC5yYW5kb20oKSAqIGFscGhhYmV0Lmxlbmd0aCkgfCAwXVxuICAgIH1cbiAgICByZXR1cm4gaWRcbiAgfVxufVxuZXhwb3J0IGxldCBuYW5vaWQgPSAoc2l6ZSA9IDIxKSA9PiB7XG4gIGxldCBpZCA9ICcnXG4gIGxldCBpID0gc2l6ZVxuICB3aGlsZSAoaS0tKSB7XG4gICAgaWQgKz0gdXJsQWxwaGFiZXRbKE1hdGgucmFuZG9tKCkgKiA2NCkgfCAwXVxuICB9XG4gIHJldHVybiBpZFxufVxuIiwgIi8qXG4gXyAgICAgX18gICAgIF8gX19cbnwgfCAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQgeyBuYW5vaWQgfSBmcm9tICduYW5vaWQvbm9uLXNlY3VyZSc7XG5cbmNvbnN0IHJ1bnRpbWVVUkwgPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luICsgXCIvd2FpbHMvcnVudGltZVwiO1xuXG4vLyBPYmplY3QgTmFtZXNcbmV4cG9ydCBjb25zdCBvYmplY3ROYW1lcyA9IHtcbiAgICBDYWxsOiAwLFxuICAgIENsaXBib2FyZDogMSxcbiAgICBBcHBsaWNhdGlvbjogMixcbiAgICBFdmVudHM6IDMsXG4gICAgQ29udGV4dE1lbnU6IDQsXG4gICAgRGlhbG9nOiA1LFxuICAgIFdpbmRvdzogNixcbiAgICBTY3JlZW5zOiA3LFxuICAgIFN5c3RlbTogOCxcbiAgICBCcm93c2VyOiA5LFxufVxuZXhwb3J0IGxldCBjbGllbnRJZCA9IG5hbm9pZCgpO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBydW50aW1lIGNhbGxlciBmdW5jdGlvbiB0aGF0IGludm9rZXMgYSBzcGVjaWZpZWQgbWV0aG9kIG9uIGEgZ2l2ZW4gb2JqZWN0IHdpdGhpbiBhIHNwZWNpZmllZCB3aW5kb3cgY29udGV4dC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IC0gVGhlIG9iamVjdCBvbiB3aGljaCB0aGUgbWV0aG9kIGlzIHRvIGJlIGludm9rZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgY29udGV4dCBpbiB3aGljaCB0aGUgbWV0aG9kIHNob3VsZCBiZSBjYWxsZWQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IEEgcnVudGltZSBjYWxsZXIgZnVuY3Rpb24gdGhhdCB0YWtlcyB0aGUgbWV0aG9kIG5hbWUgYW5kIG9wdGlvbmFsbHkgYXJndW1lbnRzIGFuZCBpbnZva2VzIHRoZSBtZXRob2Qgd2l0aGluIHRoZSBzcGVjaWZpZWQgd2luZG93IGNvbnRleHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdCwgd2luZG93TmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAobWV0aG9kLCBhcmdzPW51bGwpIHtcbiAgICAgICAgcmV0dXJuIHJ1bnRpbWVDYWxsKG9iamVjdCArIFwiLlwiICsgbWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKTtcbiAgICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcnVudGltZSBjYWxsZXIgd2l0aCBzcGVjaWZpZWQgSUQuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3QgdG8gaW52b2tlIHRoZSBtZXRob2Qgb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cuXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gLSBUaGUgbmV3IHJ1bnRpbWUgY2FsbGVyIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3QsIHdpbmRvd05hbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG1ldGhvZCwgYXJncz1udWxsKSB7XG4gICAgICAgIHJldHVybiBydW50aW1lQ2FsbFdpdGhJRChvYmplY3QsIG1ldGhvZCwgd2luZG93TmFtZSwgYXJncyk7XG4gICAgfTtcbn1cblxuXG5mdW5jdGlvbiBydW50aW1lQ2FsbChtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcbiAgICBpZiggbWV0aG9kICkge1xuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcIm1ldGhvZFwiLCBtZXRob2QpO1xuICAgIH1cbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICB9O1xuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuICAgIGlmIChhcmdzKSB7XG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiYXJnc1wiLCBKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgfVxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGZldGNoKHVybCwgZmV0Y2hPcHRpb25zKVxuICAgICAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayBjb250ZW50IHR5cGVcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpICYmIHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpLmluZGV4T2YoXCJhcHBsaWNhdGlvbi9qc29uXCIpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKHJlc3BvbnNlLnN0YXR1c1RleHQpKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbihkYXRhID0+IHJlc29sdmUoZGF0YSkpXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHJ1bnRpbWVDYWxsV2l0aElEKG9iamVjdElELCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcbiAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcIm9iamVjdFwiLCBvYmplY3RJRCk7XG4gICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJtZXRob2RcIiwgbWV0aG9kKTtcbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICB9O1xuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuICAgIGlmIChhcmdzKSB7XG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiYXJnc1wiLCBKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgfVxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBmZXRjaCh1cmwsIGZldGNoT3B0aW9ucylcbiAgICAgICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgY29udGVudCB0eXBlXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKSAmJiByZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKS5pbmRleE9mKFwiYXBwbGljYXRpb24vanNvblwiKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcihyZXNwb25zZS5zdGF0dXNUZXh0KSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oZGF0YSA9PiByZXNvbHZlKGRhdGEpKVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgIH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkJyb3dzZXIsICcnKTtcbmNvbnN0IEJyb3dzZXJPcGVuVVJMID0gMDtcblxuLyoqXG4gKiBPcGVuIGEgYnJvd3NlciB3aW5kb3cgdG8gdGhlIGdpdmVuIFVSTFxuICogQHBhcmFtIHtzdHJpbmd9IHVybCAtIFRoZSBVUkwgdG8gb3BlblxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9wZW5VUkwodXJsKSB7XG4gICAgcmV0dXJuIGNhbGwoQnJvd3Nlck9wZW5VUkwsIHt1cmx9KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkNsaXBib2FyZCwgJycpO1xuY29uc3QgQ2xpcGJvYXJkU2V0VGV4dCA9IDA7XG5jb25zdCBDbGlwYm9hcmRUZXh0ID0gMTtcblxuLyoqXG4gKiBTZXRzIHRoZSB0ZXh0IHRvIHRoZSBDbGlwYm9hcmQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgdGV4dCB0byBiZSBzZXQgdG8gdGhlIENsaXBib2FyZC5cbiAqIEByZXR1cm4ge1Byb21pc2V9IC0gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIHN1Y2Nlc3NmdWwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRUZXh0KHRleHQpIHtcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRTZXRUZXh0LCB7dGV4dH0pO1xufVxuXG4vKipcbiAqIEdldCB0aGUgQ2xpcGJvYXJkIHRleHRcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHRleHQgZnJvbSB0aGUgQ2xpcGJvYXJkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gVGV4dCgpIHtcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRUZXh0KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5sZXQgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU3lzdGVtLCAnJyk7XG5jb25zdCBzeXN0ZW1Jc0RhcmtNb2RlID0gMDtcbmNvbnN0IGVudmlyb25tZW50ID0gMTtcblxuZXhwb3J0IGZ1bmN0aW9uIGludm9rZShtc2cpIHtcbiAgICBpZih3aW5kb3cuY2hyb21lKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuY2hyb21lLndlYnZpZXcucG9zdE1lc3NhZ2UobXNnKTtcbiAgICB9XG4gICAgcmV0dXJuIHdpbmRvdy53ZWJraXQubWVzc2FnZUhhbmRsZXJzLmV4dGVybmFsLnBvc3RNZXNzYWdlKG1zZyk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBSZXRyaWV2ZXMgdGhlIHN5c3RlbSBkYXJrIG1vZGUgc3RhdHVzLlxuICogQHJldHVybnMge1Byb21pc2U8Ym9vbGVhbj59IC0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBib29sZWFuIHZhbHVlIGluZGljYXRpbmcgaWYgdGhlIHN5c3RlbSBpcyBpbiBkYXJrIG1vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0RhcmtNb2RlKCkge1xuICAgIHJldHVybiBjYWxsKHN5c3RlbUlzRGFya01vZGUpO1xufVxuXG4vKipcbiAqIEZldGNoZXMgdGhlIGNhcGFiaWxpdGllcyBvZiB0aGUgYXBwbGljYXRpb24gZnJvbSB0aGUgc2VydmVyLlxuICpcbiAqIEBhc3luY1xuICogQGZ1bmN0aW9uIENhcGFiaWxpdGllc1xuICogQHJldHVybnMge1Byb21pc2U8T2JqZWN0Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGNhcGFiaWxpdGllcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhcGFiaWxpdGllcygpIHtcbiAgICBsZXQgcmVzcG9uc2UgPSBmZXRjaChcIi93YWlscy9jYXBhYmlsaXRpZXNcIik7XG4gICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbn1cblxuLyoqXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBFbnZpcm9ubWVudEluZm9cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBPUyAtIFRoZSBvcGVyYXRpbmcgc3lzdGVtIGluIHVzZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBBcmNoIC0gVGhlIGFyY2hpdGVjdHVyZSBvZiB0aGUgc3lzdGVtLlxuICovXG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBSZXRyaWV2ZXMgZW52aXJvbm1lbnQgZGV0YWlscy5cbiAqIEByZXR1cm5zIHtQcm9taXNlPEVudmlyb25tZW50SW5mbz59IC0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgT1MgYW5kIHN5c3RlbSBhcmNoaXRlY3R1cmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFbnZpcm9ubWVudCgpIHtcbiAgICByZXR1cm4gY2FsbChlbnZpcm9ubWVudCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cy5cbiAqXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBvcGVyYXRpbmcgc3lzdGVtIGlzIFdpbmRvd3MsIG90aGVyd2lzZSBmYWxzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzV2luZG93cygpIHtcbiAgICByZXR1cm4gd2luZG93Ll93YWlscy5lbnZpcm9ubWVudC5PUyA9PT0gXCJ3aW5kb3dzXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgTGludXguXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIExpbnV4LCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0xpbnV4KCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcImxpbnV4XCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGlzIGEgbWFjT1Mgb3BlcmF0aW5nIHN5c3RlbS5cbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgZW52aXJvbm1lbnQgaXMgbWFjT1MsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzTWFjKCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcImRhcndpblwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQU1ENjQoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuQXJjaCA9PT0gXCJhbWQ2NFwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBhcmNoaXRlY3R1cmUgaXMgQVJNLlxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBjdXJyZW50IGFyY2hpdGVjdHVyZSBpcyBBUk0sIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQVJNKCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZS5cbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBSZXR1cm5zIHRydWUgaWYgdGhlIGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZSwgb3RoZXJ3aXNlIHJldHVybnMgZmFsc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0FSTTY0KCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtNjRcIjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIElzRGVidWcoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuRGVidWcgPT09IHRydWU7XG59XG5cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5pbXBvcnQge0lzRGVidWd9IGZyb20gXCIuL3N5c3RlbVwiO1xuXG4vLyBzZXR1cFxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgY29udGV4dE1lbnVIYW5kbGVyKTtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ29udGV4dE1lbnUsICcnKTtcbmNvbnN0IENvbnRleHRNZW51T3BlbiA9IDA7XG5cbmZ1bmN0aW9uIG9wZW5Db250ZXh0TWVudShpZCwgeCwgeSwgZGF0YSkge1xuICAgIHZvaWQgY2FsbChDb250ZXh0TWVudU9wZW4sIHtpZCwgeCwgeSwgZGF0YX0pO1xufVxuXG5mdW5jdGlvbiBjb250ZXh0TWVudUhhbmRsZXIoZXZlbnQpIHtcbiAgICAvLyBDaGVjayBmb3IgY3VzdG9tIGNvbnRleHQgbWVudVxuICAgIGxldCBlbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgIGxldCBjdXN0b21Db250ZXh0TWVudSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoXCItLWN1c3RvbS1jb250ZXh0bWVudVwiKTtcbiAgICBjdXN0b21Db250ZXh0TWVudSA9IGN1c3RvbUNvbnRleHRNZW51ID8gY3VzdG9tQ29udGV4dE1lbnUudHJpbSgpIDogXCJcIjtcbiAgICBpZiAoY3VzdG9tQ29udGV4dE1lbnUpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgbGV0IGN1c3RvbUNvbnRleHRNZW51RGF0YSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoXCItLWN1c3RvbS1jb250ZXh0bWVudS1kYXRhXCIpO1xuICAgICAgICBvcGVuQ29udGV4dE1lbnUoY3VzdG9tQ29udGV4dE1lbnUsIGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFksIGN1c3RvbUNvbnRleHRNZW51RGF0YSk7XG4gICAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpO1xufVxuXG5cbi8qXG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IGF1dG87IChkZWZhdWx0KSB3aWxsIHNob3cgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51IGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlIE9SIHRleHQgaGFzIGJlZW4gc2VsZWN0ZWQgT1IgZWxlbWVudCBpcyBpbnB1dCBvciB0ZXh0YXJlYVxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBzaG93OyB3aWxsIGFsd2F5cyBzaG93IHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBoaWRlOyB3aWxsIGFsd2F5cyBoaWRlIHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuXG5UaGlzIHJ1bGUgaXMgaW5oZXJpdGVkIGxpa2Ugbm9ybWFsIENTUyBydWxlcywgc28gbmVzdGluZyB3b3JrcyBhcyBleHBlY3RlZFxuKi9cbmZ1bmN0aW9uIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpIHtcblxuICAgIC8vIERlYnVnIGJ1aWxkcyBhbHdheXMgc2hvdyB0aGUgbWVudVxuICAgIGlmIChJc0RlYnVnKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFByb2Nlc3MgZGVmYXVsdCBjb250ZXh0IG1lbnVcbiAgICBjb25zdCBlbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgIGNvbnN0IGNvbXB1dGVkU3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KTtcbiAgICBjb25zdCBkZWZhdWx0Q29udGV4dE1lbnVBY3Rpb24gPSBjb21wdXRlZFN0eWxlLmdldFByb3BlcnR5VmFsdWUoXCItLWRlZmF1bHQtY29udGV4dG1lbnVcIikudHJpbSgpO1xuICAgIHN3aXRjaCAoZGVmYXVsdENvbnRleHRNZW51QWN0aW9uKSB7XG4gICAgICAgIGNhc2UgXCJzaG93XCI6XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNhc2UgXCJoaWRlXCI6XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgY29udGVudEVkaXRhYmxlIGlzIHRydWVcbiAgICAgICAgICAgIGlmIChlbGVtZW50LmlzQ29udGVudEVkaXRhYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0ZXh0IGhhcyBiZWVuIHNlbGVjdGVkXG4gICAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICAgICAgICBjb25zdCBoYXNTZWxlY3Rpb24gPSAoc2VsZWN0aW9uLnRvU3RyaW5nKCkubGVuZ3RoID4gMClcbiAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGVjdGlvbi5yYW5nZUNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdChpKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVjdHMgPSByYW5nZS5nZXRDbGllbnRSZWN0cygpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHJlY3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0ID0gcmVjdHNbal07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludChyZWN0LmxlZnQsIHJlY3QudG9wKSA9PT0gZWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRhZ25hbWUgaXMgaW5wdXQgb3IgdGV4dGFyZWFcbiAgICAgICAgICAgIGlmIChlbGVtZW50LnRhZ05hbWUgPT09IFwiSU5QVVRcIiB8fCBlbGVtZW50LnRhZ05hbWUgPT09IFwiVEVYVEFSRUFcIikge1xuICAgICAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24gfHwgKCFlbGVtZW50LnJlYWRPbmx5ICYmICFlbGVtZW50LmRpc2FibGVkKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBoaWRlIGRlZmF1bHQgY29udGV4dCBtZW51XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIFJldHJpZXZlcyB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBzcGVjaWZpZWQga2V5IGZyb20gdGhlIGZsYWcgbWFwLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXlTdHJpbmcgLSBUaGUga2V5IHRvIHJldHJpZXZlIHRoZSB2YWx1ZSBmb3IuXG4gKiBAcmV0dXJuIHsqfSAtIFRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBrZXkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRGbGFnKGtleVN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmZsYWdzW2tleVN0cmluZ107XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gcmV0cmlldmUgZmxhZyAnXCIgKyBrZXlTdHJpbmcgKyBcIic6IFwiICsgZSk7XG4gICAgfVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7aW52b2tlLCBJc1dpbmRvd3N9IGZyb20gXCIuL3N5c3RlbVwiO1xuaW1wb3J0IHtHZXRGbGFnfSBmcm9tIFwiLi9mbGFnc1wiO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLnNldFJlc2l6YWJsZSA9IHNldFJlc2l6YWJsZTtcbndpbmRvdy5fd2FpbHMuZW5kRHJhZyA9IGVuZERyYWc7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgb25Nb3VzZURvd24pO1xud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG9uTW91c2VNb3ZlKTtcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25Nb3VzZVVwKTtcblxuXG5sZXQgc2hvdWxkRHJhZyA9IGZhbHNlO1xubGV0IHJlc2l6ZUVkZ2UgPSBudWxsO1xubGV0IHJlc2l6YWJsZSA9IGZhbHNlO1xubGV0IGRlZmF1bHRDdXJzb3IgPSBcImF1dG9cIjtcblxuZnVuY3Rpb24gZHJhZ1Rlc3QoZSkge1xuICAgIGxldCB2YWwgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlLnRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZShcIi0td2Via2l0LWFwcC1yZWdpb25cIik7XG4gICAgaWYgKCF2YWwgfHwgdmFsID09PSBcIlwiIHx8IHZhbC50cmltKCkgIT09IFwiZHJhZ1wiIHx8IGUuYnV0dG9ucyAhPT0gMSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBlLmRldGFpbCA9PT0gMTtcbn1cblxuZnVuY3Rpb24gc2V0UmVzaXphYmxlKHZhbHVlKSB7XG4gICAgcmVzaXphYmxlID0gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIGVuZERyYWcoKSB7XG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5jdXJzb3IgPSAnZGVmYXVsdCc7XG4gICAgc2hvdWxkRHJhZyA9IGZhbHNlO1xufVxuXG5mdW5jdGlvbiB0ZXN0UmVzaXplKCkge1xuICAgIGlmKCByZXNpemVFZGdlICkge1xuICAgICAgICBpbnZva2UoYHJlc2l6ZToke3Jlc2l6ZUVkZ2V9YCk7XG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gb25Nb3VzZURvd24oZSkge1xuICAgIGlmKElzV2luZG93cygpICYmIHRlc3RSZXNpemUoKSB8fCBkcmFnVGVzdChlKSkge1xuICAgICAgICBzaG91bGREcmFnID0gISFpc1ZhbGlkRHJhZyhlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzVmFsaWREcmFnKGUpIHtcbiAgICAvLyBJZ25vcmUgZHJhZyBvbiBzY3JvbGxiYXJzXG4gICAgcmV0dXJuICEoZS5vZmZzZXRYID4gZS50YXJnZXQuY2xpZW50V2lkdGggfHwgZS5vZmZzZXRZID4gZS50YXJnZXQuY2xpZW50SGVpZ2h0KTtcbn1cblxuZnVuY3Rpb24gb25Nb3VzZVVwKGUpIHtcbiAgICBsZXQgbW91c2VQcmVzc2VkID0gZS5idXR0b25zICE9PSB1bmRlZmluZWQgPyBlLmJ1dHRvbnMgOiBlLndoaWNoO1xuICAgIGlmIChtb3VzZVByZXNzZWQgPiAwKSB7XG4gICAgICAgIGVuZERyYWcoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldFJlc2l6ZShjdXJzb3IgPSBkZWZhdWx0Q3Vyc29yKSB7XG4gICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmN1cnNvciA9IGN1cnNvcjtcbiAgICByZXNpemVFZGdlID0gY3Vyc29yO1xufVxuXG5mdW5jdGlvbiBvbk1vdXNlTW92ZShlKSB7XG4gICAgc2hvdWxkRHJhZyA9IGNoZWNrRHJhZyhlKTtcbiAgICBpZiAoSXNXaW5kb3dzKCkgJiYgcmVzaXphYmxlKSB7XG4gICAgICAgIGhhbmRsZVJlc2l6ZShlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrRHJhZyhlKSB7XG4gICAgbGV0IG1vdXNlUHJlc3NlZCA9IGUuYnV0dG9ucyAhPT0gdW5kZWZpbmVkID8gZS5idXR0b25zIDogZS53aGljaDtcbiAgICBpZihzaG91bGREcmFnICYmIG1vdXNlUHJlc3NlZCA+IDApIHtcbiAgICAgICAgaW52b2tlKFwiZHJhZ1wiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gc2hvdWxkRHJhZztcbn1cblxuZnVuY3Rpb24gaGFuZGxlUmVzaXplKGUpIHtcbiAgICBsZXQgcmVzaXplSGFuZGxlSGVpZ2h0ID0gR2V0RmxhZyhcInN5c3RlbS5yZXNpemVIYW5kbGVIZWlnaHRcIikgfHwgNTtcbiAgICBsZXQgcmVzaXplSGFuZGxlV2lkdGggPSBHZXRGbGFnKFwic3lzdGVtLnJlc2l6ZUhhbmRsZVdpZHRoXCIpIHx8IDU7XG5cbiAgICAvLyBFeHRyYSBwaXhlbHMgZm9yIHRoZSBjb3JuZXIgYXJlYXNcbiAgICBsZXQgY29ybmVyRXh0cmEgPSBHZXRGbGFnKFwicmVzaXplQ29ybmVyRXh0cmFcIikgfHwgMTA7XG5cbiAgICBsZXQgcmlnaHRCb3JkZXIgPSB3aW5kb3cub3V0ZXJXaWR0aCAtIGUuY2xpZW50WCA8IHJlc2l6ZUhhbmRsZVdpZHRoO1xuICAgIGxldCBsZWZ0Qm9yZGVyID0gZS5jbGllbnRYIDwgcmVzaXplSGFuZGxlV2lkdGg7XG4gICAgbGV0IHRvcEJvcmRlciA9IGUuY2xpZW50WSA8IHJlc2l6ZUhhbmRsZUhlaWdodDtcbiAgICBsZXQgYm90dG9tQm9yZGVyID0gd2luZG93Lm91dGVySGVpZ2h0IC0gZS5jbGllbnRZIDwgcmVzaXplSGFuZGxlSGVpZ2h0O1xuXG4gICAgLy8gQWRqdXN0IGZvciBjb3JuZXJzXG4gICAgbGV0IHJpZ2h0Q29ybmVyID0gd2luZG93Lm91dGVyV2lkdGggLSBlLmNsaWVudFggPCAocmVzaXplSGFuZGxlV2lkdGggKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IGxlZnRDb3JuZXIgPSBlLmNsaWVudFggPCAocmVzaXplSGFuZGxlV2lkdGggKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IHRvcENvcm5lciA9IGUuY2xpZW50WSA8IChyZXNpemVIYW5kbGVIZWlnaHQgKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IGJvdHRvbUNvcm5lciA9IHdpbmRvdy5vdXRlckhlaWdodCAtIGUuY2xpZW50WSA8IChyZXNpemVIYW5kbGVIZWlnaHQgKyBjb3JuZXJFeHRyYSk7XG5cbiAgICAvLyBJZiB3ZSBhcmVuJ3Qgb24gYW4gZWRnZSwgYnV0IHdlcmUsIHJlc2V0IHRoZSBjdXJzb3IgdG8gZGVmYXVsdFxuICAgIGlmICghbGVmdEJvcmRlciAmJiAhcmlnaHRCb3JkZXIgJiYgIXRvcEJvcmRlciAmJiAhYm90dG9tQm9yZGVyICYmIHJlc2l6ZUVkZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzZXRSZXNpemUoKTtcbiAgICB9XG4gICAgLy8gQWRqdXN0ZWQgZm9yIGNvcm5lciBhcmVhc1xuICAgIGVsc2UgaWYgKHJpZ2h0Q29ybmVyICYmIGJvdHRvbUNvcm5lcikgc2V0UmVzaXplKFwic2UtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRDb3JuZXIgJiYgYm90dG9tQ29ybmVyKSBzZXRSZXNpemUoXCJzdy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAobGVmdENvcm5lciAmJiB0b3BDb3JuZXIpIHNldFJlc2l6ZShcIm53LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BDb3JuZXIgJiYgcmlnaHRDb3JuZXIpIHNldFJlc2l6ZShcIm5lLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Qm9yZGVyKSBzZXRSZXNpemUoXCJ3LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BCb3JkZXIpIHNldFJlc2l6ZShcIm4tcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwicy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAocmlnaHRCb3JkZXIpIHNldFJlc2l6ZShcImUtcmVzaXplXCIpO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUG9zaXRpb25cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIFggY29vcmRpbmF0ZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBZIC0gVGhlIFkgY29vcmRpbmF0ZS5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNpemVcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIHdpZHRoLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFkgLSBUaGUgaGVpZ2h0LlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBSZWN0XG4gKiBAcHJvcGVydHkge251bWJlcn0gWCAtIFRoZSBYIGNvb3JkaW5hdGUgb2YgdGhlIHRvcC1sZWZ0IGNvcm5lci5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBZIC0gVGhlIFkgY29vcmRpbmF0ZSBvZiB0aGUgdG9wLWxlZnQgY29ybmVyLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSByZWN0YW5nbGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gSGVpZ2h0IC0gVGhlIGhlaWdodCBvZiB0aGUgcmVjdGFuZ2xlLlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7KCdaZXJvJ3wnTmluZXR5J3wnT25lRWlnaHR5J3wnVHdvU2V2ZW50eScpfSBSb3RhdGlvblxuICogVGhlIHJvdGF0aW9uIG9mIHRoZSBzY3JlZW4uIENhbiBiZSBvbmUgb2YgJ1plcm8nLCAnTmluZXR5JywgJ09uZUVpZ2h0eScsICdUd29TZXZlbnR5Jy5cbiAqL1xuXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gU2NyZWVuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSWQgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHNjcmVlbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBOYW1lIC0gSHVtYW4gcmVhZGFibGUgbmFtZSBvZiB0aGUgc2NyZWVuLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFNjYWxlIC0gVGhlIHJlc29sdXRpb24gc2NhbGUgb2YgdGhlIHNjcmVlbi4gMSA9IHN0YW5kYXJkIHJlc29sdXRpb24sIDIgPSBoaWdoIChSZXRpbmEpLCBldGMuXG4gKiBAcHJvcGVydHkge1Bvc2l0aW9ufSBQb3NpdGlvbiAtIENvbnRhaW5zIHRoZSBYIGFuZCBZIGNvb3JkaW5hdGVzIG9mIHRoZSBzY3JlZW4ncyBwb3NpdGlvbi5cbiAqIEBwcm9wZXJ0eSB7U2l6ZX0gU2l6ZSAtIENvbnRhaW5zIHRoZSB3aWR0aCBhbmQgaGVpZ2h0IG9mIHRoZSBzY3JlZW4uXG4gKiBAcHJvcGVydHkge1JlY3R9IEJvdW5kcyAtIENvbnRhaW5zIHRoZSBib3VuZHMgb2YgdGhlIHNjcmVlbiBpbiB0ZXJtcyBvZiBYLCBZLCBXaWR0aCwgYW5kIEhlaWdodC5cbiAqIEBwcm9wZXJ0eSB7UmVjdH0gV29ya0FyZWEgLSBDb250YWlucyB0aGUgYXJlYSBvZiB0aGUgc2NyZWVuIHRoYXQgaXMgYWN0dWFsbHkgdXNhYmxlIChleGNsdWRpbmcgdGFza2JhciBhbmQgb3RoZXIgc3lzdGVtIFVJKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gSXNQcmltYXJ5IC0gVHJ1ZSBpZiB0aGlzIGlzIHRoZSBwcmltYXJ5IG1vbml0b3Igc2VsZWN0ZWQgYnkgdGhlIHVzZXIgaW4gdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gKiBAcHJvcGVydHkge1JvdGF0aW9ufSBSb3RhdGlvbiAtIFRoZSByb3RhdGlvbiBvZiB0aGUgc2NyZWVuLlxuICovXG5cblxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU2NyZWVucywgJycpO1xuXG5jb25zdCBnZXRBbGwgPSAwO1xuY29uc3QgZ2V0UHJpbWFyeSA9IDE7XG5jb25zdCBnZXRDdXJyZW50ID0gMjtcblxuLyoqXG4gKiBHZXRzIGFsbCBzY3JlZW5zLlxuICogQHJldHVybnMge1Byb21pc2U8U2NyZWVuW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiBTY3JlZW4gb2JqZWN0cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldEFsbCgpIHtcbiAgICByZXR1cm4gY2FsbChnZXRBbGwpO1xufVxuLyoqXG4gKiBHZXRzIHRoZSBwcmltYXJ5IHNjcmVlbi5cbiAqIEByZXR1cm5zIHtQcm9taXNlPFNjcmVlbj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBwcmltYXJ5IHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldFByaW1hcnkoKSB7XG4gICAgcmV0dXJuIGNhbGwoZ2V0UHJpbWFyeSk7XG59XG4vKipcbiAqIEdldHMgdGhlIGN1cnJlbnQgYWN0aXZlIHNjcmVlbi5cbiAqXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxTY3JlZW4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjdXJyZW50IGFjdGl2ZSBzY3JlZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRDdXJyZW50KCkge1xuICAgIHJldHVybiBjYWxsKGdldEN1cnJlbnQpO1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vLyBJbXBvcnQgc2NyZWVuIGpzZG9jIGRlZmluaXRpb24gZnJvbSAuL3NjcmVlbnMuanNcbi8qKlxuICogQHR5cGVkZWYge2ltcG9ydChcIi4vc2NyZWVuc1wiKS5TY3JlZW59IFNjcmVlblxuICovXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcblxuY29uc3QgY2VudGVyID0gMDtcbmNvbnN0IHNldFRpdGxlID0gMTtcbmNvbnN0IGZ1bGxzY3JlZW4gPSAyO1xuY29uc3QgdW5GdWxsc2NyZWVuID0gMztcbmNvbnN0IHNldFNpemUgPSA0O1xuY29uc3Qgc2l6ZSA9IDU7XG5jb25zdCBzZXRNYXhTaXplID0gNjtcbmNvbnN0IHNldE1pblNpemUgPSA3O1xuY29uc3Qgc2V0QWx3YXlzT25Ub3AgPSA4O1xuY29uc3Qgc2V0UmVsYXRpdmVQb3NpdGlvbiA9IDk7XG5jb25zdCByZWxhdGl2ZVBvc2l0aW9uID0gMTA7XG5jb25zdCBzY3JlZW4gPSAxMTtcbmNvbnN0IGhpZGUgPSAxMjtcbmNvbnN0IG1heGltaXNlID0gMTM7XG5jb25zdCB1bk1heGltaXNlID0gMTQ7XG5jb25zdCB0b2dnbGVNYXhpbWlzZSA9IDE1O1xuY29uc3QgbWluaW1pc2UgPSAxNjtcbmNvbnN0IHVuTWluaW1pc2UgPSAxNztcbmNvbnN0IHJlc3RvcmUgPSAxODtcbmNvbnN0IHNob3cgPSAxOTtcbmNvbnN0IGNsb3NlID0gMjA7XG5jb25zdCBzZXRCYWNrZ3JvdW5kQ29sb3VyID0gMjE7XG5jb25zdCBzZXRSZXNpemFibGUgPSAyMjtcbmNvbnN0IHdpZHRoID0gMjM7XG5jb25zdCBoZWlnaHQgPSAyNDtcbmNvbnN0IHpvb21JbiA9IDI1O1xuY29uc3Qgem9vbU91dCA9IDI2O1xuY29uc3Qgem9vbVJlc2V0ID0gMjc7XG5jb25zdCBnZXRab29tTGV2ZWwgPSAyODtcbmNvbnN0IHNldFpvb21MZXZlbCA9IDI5O1xuXG5jb25zdCB0aGlzV2luZG93ID0gR2V0KCcnKTtcblxuZnVuY3Rpb24gY3JlYXRlV2luZG93KGNhbGwpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBHZXQ6ICh3aW5kb3dOYW1lKSA9PiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKSxcbiAgICAgICAgQ2VudGVyOiAoKSA9PiBjYWxsKGNlbnRlciksXG4gICAgICAgIFNldFRpdGxlOiAodGl0bGUpID0+IGNhbGwoc2V0VGl0bGUsIHt0aXRsZX0pLFxuICAgICAgICBGdWxsc2NyZWVuOiAoKSA9PiBjYWxsKGZ1bGxzY3JlZW4pLFxuICAgICAgICBVbkZ1bGxzY3JlZW46ICgpID0+IGNhbGwodW5GdWxsc2NyZWVuKSxcbiAgICAgICAgU2V0U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2l6ZTogKCkgPT4gY2FsbChzaXplKSxcbiAgICAgICAgU2V0TWF4U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWF4U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2V0TWluU2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWluU2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2V0QWx3YXlzT25Ub3A6IChvblRvcCkgPT4gY2FsbChzZXRBbHdheXNPblRvcCwge2Fsd2F5c09uVG9wOiBvblRvcH0pLFxuICAgICAgICBTZXRSZWxhdGl2ZVBvc2l0aW9uOiAoeCwgeSkgPT4gY2FsbChzZXRSZWxhdGl2ZVBvc2l0aW9uLCB7eCwgeX0pLFxuICAgICAgICBSZWxhdGl2ZVBvc2l0aW9uOiAoKSA9PiBjYWxsKHJlbGF0aXZlUG9zaXRpb24pLFxuICAgICAgICBTY3JlZW46ICgpID0+IGNhbGwoc2NyZWVuKSxcbiAgICAgICAgSGlkZTogKCkgPT4gY2FsbChoaWRlKSxcbiAgICAgICAgTWF4aW1pc2U6ICgpID0+IGNhbGwobWF4aW1pc2UpLFxuICAgICAgICBVbk1heGltaXNlOiAoKSA9PiBjYWxsKHVuTWF4aW1pc2UpLFxuICAgICAgICBUb2dnbGVNYXhpbWlzZTogKCkgPT4gY2FsbCh0b2dnbGVNYXhpbWlzZSksXG4gICAgICAgIE1pbmltaXNlOiAoKSA9PiBjYWxsKG1pbmltaXNlKSxcbiAgICAgICAgVW5NaW5pbWlzZTogKCkgPT4gY2FsbCh1bk1pbmltaXNlKSxcbiAgICAgICAgUmVzdG9yZTogKCkgPT4gY2FsbChyZXN0b3JlKSxcbiAgICAgICAgU2hvdzogKCkgPT4gY2FsbChzaG93KSxcbiAgICAgICAgQ2xvc2U6ICgpID0+IGNhbGwoY2xvc2UpLFxuICAgICAgICBTZXRCYWNrZ3JvdW5kQ29sb3VyOiAociwgZywgYiwgYSkgPT4gY2FsbChzZXRCYWNrZ3JvdW5kQ29sb3VyLCB7ciwgZywgYiwgYX0pLFxuICAgICAgICBTZXRSZXNpemFibGU6IChyZXNpemFibGUpID0+IGNhbGwoc2V0UmVzaXphYmxlLCB7cmVzaXphYmxlfSksXG4gICAgICAgIFdpZHRoOiAoKSA9PiBjYWxsKHdpZHRoKSxcbiAgICAgICAgSGVpZ2h0OiAoKSA9PiBjYWxsKGhlaWdodCksXG4gICAgICAgIFpvb21JbjogKCkgPT4gY2FsbCh6b29tSW4pLFxuICAgICAgICBab29tT3V0OiAoKSA9PiBjYWxsKHpvb21PdXQpLFxuICAgICAgICBab29tUmVzZXQ6ICgpID0+IGNhbGwoem9vbVJlc2V0KSxcbiAgICAgICAgR2V0Wm9vbUxldmVsOiAoKSA9PiBjYWxsKGdldFpvb21MZXZlbCksXG4gICAgICAgIFNldFpvb21MZXZlbDogKHpvb21MZXZlbCkgPT4gY2FsbChzZXRab29tTGV2ZWwsIHt6b29tTGV2ZWx9KSxcbiAgICB9O1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNwZWNpZmllZCB3aW5kb3cuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHdpbmRvd05hbWUgLSBUaGUgbmFtZSBvZiB0aGUgd2luZG93IHRvIGdldC5cbiAqIEByZXR1cm4ge09iamVjdH0gLSBUaGUgc3BlY2lmaWVkIHdpbmRvdyBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXQod2luZG93TmFtZSkge1xuICAgIHJldHVybiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKTtcbn1cblxuLyoqXG4gKiBDZW50ZXJzIHRoZSB3aW5kb3cgb24gdGhlIHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENlbnRlcigpIHtcbiAgICB0aGlzV2luZG93LkNlbnRlcigpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIHRpdGxlIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGUgLSBUaGUgdGl0bGUgdG8gc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0VGl0bGUodGl0bGUpIHtcbiAgICB0aGlzV2luZG93LlNldFRpdGxlKHRpdGxlKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSB3aW5kb3cgdG8gZnVsbHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEZ1bGxzY3JlZW4oKSB7XG4gICAgdGhpc1dpbmRvdy5GdWxsc2NyZWVuKCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgc2l6ZSBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdGhpc1dpbmRvdy5TZXRTaXplKHdpZHRoLCBoZWlnaHQpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNpemUoKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2l6ZSgpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIG1heGltdW0gd2lkdGggb2YgdGhlIHdpbmRvdy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgLSBUaGUgbWF4aW11bSBoZWlnaHQgb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldE1heFNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXNXaW5kb3cuU2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aCAtIFRoZSBtaW5pbXVtIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIG1pbmltdW0gaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzV2luZG93LlNldE1pblNpemUod2lkdGgsIGhlaWdodCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgd2luZG93IHRvIGFsd2F5cyBiZSBvbiB0b3AuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IG9uVG9wIC0gV2hldGhlciB0aGUgd2luZG93IHNob3VsZCBhbHdheXMgYmUgb24gdG9wLlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0QWx3YXlzT25Ub3Aob25Ub3ApIHtcbiAgICB0aGlzV2luZG93LlNldEFsd2F5c09uVG9wKG9uVG9wKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSByZWxhdGl2ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHggLSBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSB3aW5kb3cncyBwb3NpdGlvbi5cbiAqIEBwYXJhbSB7bnVtYmVyfSB5IC0gVGhlIHktY29vcmRpbmF0ZSBvZiB0aGUgd2luZG93J3MgcG9zaXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRSZWxhdGl2ZVBvc2l0aW9uKHgsIHkpIHtcbiAgICB0aGlzV2luZG93LlNldFJlbGF0aXZlUG9zaXRpb24oeCwgeSk7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFJlbGF0aXZlUG9zaXRpb24oKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuUmVsYXRpdmVQb3NpdGlvbigpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNjcmVlbiB0aGF0IHRoZSB3aW5kb3cgaXMgb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTY3JlZW4oKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2NyZWVuKCk7XG59XG5cbi8qKlxuICogSGlkZXMgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XG4gICAgdGhpc1dpbmRvdy5IaWRlKCk7XG59XG5cbi8qKlxuICogTWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBNYXhpbWlzZSgpIHtcbiAgICB0aGlzV2luZG93Lk1heGltaXNlKCk7XG59XG5cbi8qKlxuICogVW4tbWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBVbk1heGltaXNlKCkge1xuICAgIHRoaXNXaW5kb3cuVW5NYXhpbWlzZSgpO1xufVxuXG4vKipcbiAqIFRvZ2dsZXMgdGhlIG1heGltaXNhdGlvbiBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gVG9nZ2xlTWF4aW1pc2UoKSB7XG4gICAgdGhpc1dpbmRvdy5Ub2dnbGVNYXhpbWlzZSgpO1xufVxuXG4vKipcbiAqIE1pbmltaXNlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gTWluaW1pc2UoKSB7XG4gICAgdGhpc1dpbmRvdy5NaW5pbWlzZSgpO1xufVxuXG4vKipcbiAqIFVuLW1pbmltaXNlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gVW5NaW5pbWlzZSgpIHtcbiAgICB0aGlzV2luZG93LlVuTWluaW1pc2UoKTtcbn1cblxuLyoqXG4gKiBSZXN0b3JlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVzdG9yZSgpIHtcbiAgICB0aGlzV2luZG93LlJlc3RvcmUoKTtcbn1cblxuLyoqXG4gKiBTaG93cyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpIHtcbiAgICB0aGlzV2luZG93LlNob3coKTtcbn1cblxuLyoqXG4gKiBDbG9zZXMgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENsb3NlKCkge1xuICAgIHRoaXNXaW5kb3cuQ2xvc2UoKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBiYWNrZ3JvdW5kIGNvbG91ciBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHIgLSBUaGUgcmVkIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxuICogQHBhcmFtIHtudW1iZXJ9IGcgLSBUaGUgZ3JlZW4gY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXG4gKiBAcGFyYW0ge251bWJlcn0gYiAtIFRoZSBibHVlIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxuICogQHBhcmFtIHtudW1iZXJ9IGEgLSBUaGUgYWxwaGEgY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRCYWNrZ3JvdW5kQ29sb3VyKHIsIGcsIGIsIGEpIHtcbiAgICB0aGlzV2luZG93LlNldEJhY2tncm91bmRDb2xvdXIociwgZywgYiwgYSk7XG59XG5cbi8qKlxuICogU2V0cyB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgcmVzaXphYmxlLlxuICogQHBhcmFtIHtib29sZWFufSByZXNpemFibGUgLSBXaGV0aGVyIHRoZSB3aW5kb3cgc2hvdWxkIGJlIHJlc2l6YWJsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldFJlc2l6YWJsZShyZXNpemFibGUpIHtcbiAgICB0aGlzV2luZG93LlNldFJlc2l6YWJsZShyZXNpemFibGUpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaWR0aCgpIHtcbiAgICByZXR1cm4gdGhpc1dpbmRvdy5XaWR0aCgpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gSGVpZ2h0KCkge1xuICAgIHJldHVybiB0aGlzV2luZG93LkhlaWdodCgpO1xufVxuXG4vKipcbiAqIFpvb21zIGluIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBab29tSW4oKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tSW4oKTtcbn1cblxuLyoqXG4gKiBab29tcyBvdXQgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFpvb21PdXQoKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tT3V0KCk7XG59XG5cbi8qKlxuICogUmVzZXRzIHRoZSB6b29tIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBab29tUmVzZXQoKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tUmVzZXQoKTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRab29tTGV2ZWwoKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuR2V0Wm9vbUxldmVsKCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHpvb21MZXZlbCAtIFRoZSB6b29tIGxldmVsIHRvIHNldC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldFpvb21MZXZlbCh6b29tTGV2ZWwpIHtcbiAgICB0aGlzV2luZG93LlNldFpvb21MZXZlbCh6b29tTGV2ZWwpO1xufVxuIiwgIlxuaW1wb3J0IHtFbWl0LCBXYWlsc0V2ZW50fSBmcm9tIFwiLi9ldmVudHNcIjtcbmltcG9ydCB7UXVlc3Rpb259IGZyb20gXCIuL2RpYWxvZ3NcIjtcbmltcG9ydCB7R2V0fSBmcm9tIFwiLi93aW5kb3dcIjtcbmltcG9ydCB7T3BlblVSTH0gZnJvbSBcIi4vYnJvd3NlclwiO1xuXG4vKipcbiAqIFNlbmRzIGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIG9wdGlvbmFsIGRhdGEuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBzZW5kLlxuICogQHBhcmFtIHthbnl9IFtkYXRhPW51bGxdIC0gT3B0aW9uYWwgZGF0YSB0byBzZW5kIGFsb25nIHdpdGggdGhlIGV2ZW50LlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHNlbmRFdmVudChldmVudE5hbWUsIGRhdGE9bnVsbCkge1xuICAgIGxldCBldmVudCA9IG5ldyBXYWlsc0V2ZW50KGV2ZW50TmFtZSwgZGF0YSk7XG4gICAgRW1pdChldmVudCk7XG59XG5cbi8qKlxuICogQWRkcyBldmVudCBsaXN0ZW5lcnMgdG8gZWxlbWVudHMgd2l0aCBgd21sLWV2ZW50YCBhdHRyaWJ1dGUuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gYWRkV01MRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLWV2ZW50XScpO1xuICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZXZlbnRUeXBlID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1ldmVudCcpO1xuICAgICAgICBjb25zdCBjb25maXJtID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1jb25maXJtJyk7XG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XG5cbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIERldGFjaGVkOiBmYWxzZSwgQnV0dG9uczpbe0xhYmVsOlwiWWVzXCJ9LHtMYWJlbDpcIk5vXCIsIElzRGVmYXVsdDp0cnVlfV19KS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPT0gXCJOb1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kRXZlbnQoZXZlbnRUeXBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbmRFdmVudChldmVudFR5cGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFJlbW92ZSBleGlzdGluZyBsaXN0ZW5lcnNcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcblxuICAgICAgICAvLyBBZGQgbmV3IGxpc3RlbmVyXG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XG4gICAgfSk7XG59XG5cblxuLyoqXG4gKiBDYWxscyBhIG1ldGhvZCBvbiBhIHNwZWNpZmllZCB3aW5kb3cuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgdG8gY2FsbCB0aGUgbWV0aG9kIG9uLlxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZCAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqL1xuZnVuY3Rpb24gY2FsbFdpbmRvd01ldGhvZCh3aW5kb3dOYW1lLCBtZXRob2QpIHtcbiAgICBsZXQgdGFyZ2V0V2luZG93ID0gR2V0KHdpbmRvd05hbWUpO1xuICAgIGxldCBtZXRob2RNYXAgPSBXaW5kb3dNZXRob2RzKHRhcmdldFdpbmRvdyk7XG4gICAgaWYgKCFtZXRob2RNYXAuaGFzKG1ldGhvZCkpIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJXaW5kb3cgbWV0aG9kIFwiICsgbWV0aG9kICsgXCIgbm90IGZvdW5kXCIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBtZXRob2RNYXAuZ2V0KG1ldGhvZCkoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBjYWxsaW5nIHdpbmRvdyBtZXRob2QgJ1wiICsgbWV0aG9kICsgXCInOiBcIiArIGUpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBZGRzIHdpbmRvdyBsaXN0ZW5lcnMgZm9yIGVsZW1lbnRzIHdpdGggdGhlICd3bWwtd2luZG93JyBhdHRyaWJ1dGUuXG4gKiBSZW1vdmVzIGFueSBleGlzdGluZyBsaXN0ZW5lcnMgYmVmb3JlIGFkZGluZyBuZXcgb25lcy5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5mdW5jdGlvbiBhZGRXTUxXaW5kb3dMaXN0ZW5lcnMoKSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLXdpbmRvd10nKTtcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IHdpbmRvd01ldGhvZCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtd2luZG93Jyk7XG4gICAgICAgIGNvbnN0IGNvbmZpcm0gPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWNvbmZpcm0nKTtcbiAgICAgICAgY29uc3QgdHJpZ2dlciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdHJpZ2dlcicpIHx8ICdjbGljayc7XG4gICAgICAgIGNvbnN0IHRhcmdldFdpbmRvdyA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdGFyZ2V0LXdpbmRvdycpIHx8ICcnO1xuXG4gICAgICAgIGxldCBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjb25maXJtKSB7XG4gICAgICAgICAgICAgICAgUXVlc3Rpb24oe1RpdGxlOiBcIkNvbmZpcm1cIiwgTWVzc2FnZTpjb25maXJtLCBCdXR0b25zOlt7TGFiZWw6XCJZZXNcIn0se0xhYmVsOlwiTm9cIiwgSXNEZWZhdWx0OnRydWV9XX0pLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9PSBcIk5vXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxXaW5kb3dNZXRob2QodGFyZ2V0V2luZG93LCB3aW5kb3dNZXRob2QpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FsbFdpbmRvd01ldGhvZCh0YXJnZXRXaW5kb3csIHdpbmRvd01ldGhvZCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUmVtb3ZlIGV4aXN0aW5nIGxpc3RlbmVyc1xuICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xuXG4gICAgICAgIC8vIEFkZCBuZXcgbGlzdGVuZXJcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBBZGRzIGEgbGlzdGVuZXIgdG8gZWxlbWVudHMgd2l0aCB0aGUgJ3dtbC1vcGVudXJsJyBhdHRyaWJ1dGUuXG4gKiBXaGVuIHRoZSBzcGVjaWZpZWQgdHJpZ2dlciBldmVudCBpcyBmaXJlZCBvbiBhbnkgb2YgdGhlc2UgZWxlbWVudHMsXG4gKiB0aGUgbGlzdGVuZXIgd2lsbCBvcGVuIHRoZSBVUkwgc3BlY2lmaWVkIGJ5IHRoZSAnd21sLW9wZW51cmwnIGF0dHJpYnV0ZS5cbiAqIElmIGEgJ3dtbC1jb25maXJtJyBhdHRyaWJ1dGUgaXMgcHJvdmlkZWQsIGEgY29uZmlybWF0aW9uIGRpYWxvZyB3aWxsIGJlIGRpc3BsYXllZCxcbiAqIGFuZCB0aGUgVVJMIHdpbGwgb25seSBiZSBvcGVuZWQgaWYgdGhlIHVzZXIgY29uZmlybXMuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpIHtcbiAgICBjb25zdCBlbGVtZW50cyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ1t3bWwtb3BlbnVybF0nKTtcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IHVybCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtb3BlbnVybCcpO1xuICAgICAgICBjb25zdCBjb25maXJtID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1jb25maXJtJyk7XG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XG5cbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIEJ1dHRvbnM6W3tMYWJlbDpcIlllc1wifSx7TGFiZWw6XCJOb1wiLCBJc0RlZmF1bHQ6dHJ1ZX1dfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT09IFwiTm9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCBPcGVuVVJMKHVybCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2b2lkIE9wZW5VUkwodXJsKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZW1vdmUgZXhpc3RpbmcgbGlzdGVuZXJzXG4gICAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XG5cbiAgICAgICAgLy8gQWRkIG5ldyBsaXN0ZW5lclxuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIFJlbG9hZHMgdGhlIFdNTCBwYWdlIGJ5IGFkZGluZyBuZWNlc3NhcnkgZXZlbnQgbGlzdGVuZXJzIGFuZCBicm93c2VyIGxpc3RlbmVycy5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVsb2FkKCkge1xuICAgIGFkZFdNTEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgYWRkV01MV2luZG93TGlzdGVuZXJzKCk7XG4gICAgYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBtYXAgb2YgYWxsIG1ldGhvZHMgaW4gdGhlIGN1cnJlbnQgd2luZG93LlxuICogQHJldHVybnMge01hcH0gLSBBIG1hcCBvZiB3aW5kb3cgbWV0aG9kcy5cbiAqL1xuZnVuY3Rpb24gV2luZG93TWV0aG9kcyh0YXJnZXRXaW5kb3cpIHtcbiAgICAvLyBDcmVhdGUgYSBuZXcgbWFwIHRvIHN0b3JlIG1ldGhvZHNcbiAgICBsZXQgcmVzdWx0ID0gbmV3IE1hcCgpO1xuXG4gICAgLy8gSXRlcmF0ZSBvdmVyIGFsbCBwcm9wZXJ0aWVzIG9mIHRoZSB3aW5kb3cgb2JqZWN0XG4gICAgZm9yIChsZXQgbWV0aG9kIGluIHRhcmdldFdpbmRvdykge1xuICAgICAgICAvLyBDaGVjayBpZiB0aGUgcHJvcGVydHkgaXMgaW5kZWVkIGEgbWV0aG9kIChmdW5jdGlvbilcbiAgICAgICAgaWYodHlwZW9mIHRhcmdldFdpbmRvd1ttZXRob2RdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAvLyBBZGQgdGhlIG1ldGhvZCB0byB0aGUgbWFwXG4gICAgICAgICAgICByZXN1bHQuc2V0KG1ldGhvZCwgdGFyZ2V0V2luZG93W21ldGhvZF0pO1xuICAgICAgICB9XG5cbiAgICB9XG4gICAgLy8gUmV0dXJuIHRoZSBtYXAgb2Ygd2luZG93IG1ldGhvZHNcbiAgICByZXR1cm4gcmVzdWx0O1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtpbXBvcnQoXCIuL3R5cGVzXCIpLldhaWxzRXZlbnR9IFdhaWxzRXZlbnRcbiAqL1xuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuXG5pbXBvcnQge0V2ZW50VHlwZXN9IGZyb20gXCIuL2V2ZW50X3R5cGVzXCI7XG5leHBvcnQgY29uc3QgVHlwZXMgPSBFdmVudFR5cGVzO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLmRpc3BhdGNoV2FpbHNFdmVudCA9IGRpc3BhdGNoV2FpbHNFdmVudDtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuRXZlbnRzLCAnJyk7XG5jb25zdCBFbWl0TWV0aG9kID0gMDtcbmNvbnN0IGV2ZW50TGlzdGVuZXJzID0gbmV3IE1hcCgpO1xuXG5jbGFzcyBMaXN0ZW5lciB7XG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgICAgIHRoaXMuZXZlbnROYW1lID0gZXZlbnROYW1lO1xuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICAgICAgdGhpcy5DYWxsYmFjayA9IChkYXRhKSA9PiB7XG4gICAgICAgICAgICBjYWxsYmFjayhkYXRhKTtcbiAgICAgICAgICAgIGlmICh0aGlzLm1heENhbGxiYWNrcyA9PT0gLTEpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMubWF4Q2FsbGJhY2tzIC09IDE7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXhDYWxsYmFja3MgPT09IDA7XG4gICAgICAgIH07XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2FpbHNFdmVudCB7XG4gICAgY29uc3RydWN0b3IobmFtZSwgZGF0YSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cCgpIHtcbn1cblxuZnVuY3Rpb24gZGlzcGF0Y2hXYWlsc0V2ZW50KGV2ZW50KSB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudC5uYW1lKTtcbiAgICBpZiAobGlzdGVuZXJzKSB7XG4gICAgICAgIGxldCB0b1JlbW92ZSA9IGxpc3RlbmVycy5maWx0ZXIobGlzdGVuZXIgPT4ge1xuICAgICAgICAgICAgbGV0IHJlbW92ZSA9IGxpc3RlbmVyLkNhbGxiYWNrKGV2ZW50KTtcbiAgICAgICAgICAgIGlmIChyZW1vdmUpIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHRvUmVtb3ZlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVycy5maWx0ZXIobCA9PiAhdG9SZW1vdmUuaW5jbHVkZXMobCkpO1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5sZW5ndGggPT09IDApIGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudC5uYW1lKTtcbiAgICAgICAgICAgIGVsc2UgZXZlbnRMaXN0ZW5lcnMuc2V0KGV2ZW50Lm5hbWUsIGxpc3RlbmVycyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogUmVnaXN0ZXIgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgbXVsdGlwbGUgdGltZXMgZm9yIGEgc3BlY2lmaWMgZXZlbnQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZWdpc3RlciB0aGUgY2FsbGJhY2sgZm9yLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIHRyaWdnZXJlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3MgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdGhlIGNhbGxiYWNrIGNhbiBiZSBjYWxsZWQgZm9yIHRoZSBldmVudC4gT25jZSB0aGUgbWF4aW11bSBudW1iZXIgaXMgcmVhY2hlZCwgdGhlIGNhbGxiYWNrIHdpbGwgbm8gbG9uZ2VyIGJlIGNhbGxlZC5cbiAqXG4gQHJldHVybiB7ZnVuY3Rpb259IC0gQSBmdW5jdGlvbiB0aGF0LCB3aGVuIGNhbGxlZCwgd2lsbCB1bnJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmcm9tIHRoZSBldmVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudE5hbWUpIHx8IFtdO1xuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xuICAgIGxpc3RlbmVycy5wdXNoKHRoaXNMaXN0ZW5lcik7XG4gICAgZXZlbnRMaXN0ZW5lcnMuc2V0KGV2ZW50TmFtZSwgbGlzdGVuZXJzKTtcbiAgICByZXR1cm4gKCkgPT4gbGlzdGVuZXJPZmYodGhpc0xpc3RlbmVyKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuIHRoZSBzcGVjaWZpZWQgZXZlbnQgb2NjdXJzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFjayAtIFRoZSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZC4gSXQgdGFrZXMgbm8gcGFyYW1ldGVycy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuICovXG5leHBvcnQgZnVuY3Rpb24gT24oZXZlbnROYW1lLCBjYWxsYmFjaykgeyByZXR1cm4gT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAtMSk7IH1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmx5IG9uY2UgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudC5cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGV2ZW50IG9jY3Vycy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHsgcmV0dXJuIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgMSk7IH1cblxuLyoqXG4gKiBSZW1vdmVzIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIgZnJvbSB0aGUgZXZlbnQgbGlzdGVuZXJzIGNvbGxlY3Rpb24uXG4gKiBJZiBhbGwgbGlzdGVuZXJzIGZvciB0aGUgZXZlbnQgYXJlIHJlbW92ZWQsIHRoZSBldmVudCBrZXkgaXMgZGVsZXRlZCBmcm9tIHRoZSBjb2xsZWN0aW9uLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBsaXN0ZW5lciAtIFRoZSBsaXN0ZW5lciB0byBiZSByZW1vdmVkLlxuICovXG5mdW5jdGlvbiBsaXN0ZW5lck9mZihsaXN0ZW5lcikge1xuICAgIGNvbnN0IGV2ZW50TmFtZSA9IGxpc3RlbmVyLmV2ZW50TmFtZTtcbiAgICBsZXQgbGlzdGVuZXJzID0gZXZlbnRMaXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSkuZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuICAgIGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSBldmVudExpc3RlbmVycy5kZWxldGUoZXZlbnROYW1lKTtcbiAgICBlbHNlIGV2ZW50TGlzdGVuZXJzLnNldChldmVudE5hbWUsIGxpc3RlbmVycyk7XG59XG5cblxuLyoqXG4gKiBSZW1vdmVzIGV2ZW50IGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudCBuYW1lcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSBsaXN0ZW5lcnMgZm9yLlxuICogQHBhcmFtIHsuLi5zdHJpbmd9IGFkZGl0aW9uYWxFdmVudE5hbWVzIC0gQWRkaXRpb25hbCBldmVudCBuYW1lcyB0byByZW1vdmUgbGlzdGVuZXJzIGZvci5cbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9mZihldmVudE5hbWUsIC4uLmFkZGl0aW9uYWxFdmVudE5hbWVzKSB7XG4gICAgbGV0IGV2ZW50c1RvUmVtb3ZlID0gW2V2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXNdO1xuICAgIGV2ZW50c1RvUmVtb3ZlLmZvckVhY2goZXZlbnROYW1lID0+IGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudE5hbWUpKTtcbn1cbi8qKlxuICogUmVtb3ZlcyBhbGwgZXZlbnQgbGlzdGVuZXJzLlxuICpcbiAqIEBmdW5jdGlvbiBPZmZBbGxcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gT2ZmQWxsKCkgeyBldmVudExpc3RlbmVycy5jbGVhcigpOyB9XG5cbi8qKlxuICogRW1pdHMgYW4gZXZlbnQgdXNpbmcgdGhlIGdpdmVuIGV2ZW50IG5hbWUuXG4gKlxuICogQHBhcmFtIHtXYWlsc0V2ZW50fSBldmVudCAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBlbWl0LlxuICogQHJldHVybnMge2FueX0gLSBUaGUgcmVzdWx0IG9mIHRoZSBlbWl0dGVkIGV2ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gRW1pdChldmVudCkgeyByZXR1cm4gY2FsbChFbWl0TWV0aG9kLCBldmVudCk7IH1cbiIsICJcbmV4cG9ydCBjb25zdCBFdmVudFR5cGVzID0ge1xuXHRXaW5kb3dzOiB7XG5cdFx0U3lzdGVtVGhlbWVDaGFuZ2VkOiBcIndpbmRvd3M6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdFx0QVBNUG93ZXJTdGF0dXNDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclN0YXR1c0NoYW5nZVwiLFxuXHRcdEFQTVN1c3BlbmQ6IFwid2luZG93czpBUE1TdXNwZW5kXCIsXG5cdFx0QVBNUmVzdW1lQXV0b21hdGljOiBcIndpbmRvd3M6QVBNUmVzdW1lQXV0b21hdGljXCIsXG5cdFx0QVBNUmVzdW1lU3VzcGVuZDogXCJ3aW5kb3dzOkFQTVJlc3VtZVN1c3BlbmRcIixcblx0XHRBUE1Qb3dlclNldHRpbmdDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclNldHRpbmdDaGFuZ2VcIixcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwid2luZG93czpBcHBsaWNhdGlvblN0YXJ0ZWRcIixcblx0XHRXZWJWaWV3TmF2aWdhdGlvbkNvbXBsZXRlZDogXCJ3aW5kb3dzOldlYlZpZXdOYXZpZ2F0aW9uQ29tcGxldGVkXCIsXG5cdFx0V2luZG93SW5hY3RpdmU6IFwid2luZG93czpXaW5kb3dJbmFjdGl2ZVwiLFxuXHRcdFdpbmRvd0FjdGl2ZTogXCJ3aW5kb3dzOldpbmRvd0FjdGl2ZVwiLFxuXHRcdFdpbmRvd0NsaWNrQWN0aXZlOiBcIndpbmRvd3M6V2luZG93Q2xpY2tBY3RpdmVcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcIndpbmRvd3M6V2luZG93RnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1VuRnVsbHNjcmVlbjogXCJ3aW5kb3dzOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwid2luZG93czpXaW5kb3dSZXN0b3JlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwid2luZG93czpXaW5kb3dNaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWluaW1pc2U6IFwid2luZG93czpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2U6IFwid2luZG93czpXaW5kb3dDbG9zZVwiLFxuXHRcdFdpbmRvd1NldEZvY3VzOiBcIndpbmRvd3M6V2luZG93U2V0Rm9jdXNcIixcblx0XHRXaW5kb3dLaWxsRm9jdXM6IFwid2luZG93czpXaW5kb3dLaWxsRm9jdXNcIixcblx0XHRXaW5kb3dEcmFnRHJvcDogXCJ3aW5kb3dzOldpbmRvd0RyYWdEcm9wXCIsXG5cdFx0V2luZG93RHJhZ0VudGVyOiBcIndpbmRvd3M6V2luZG93RHJhZ0VudGVyXCIsXG5cdFx0V2luZG93RHJhZ0xlYXZlOiBcIndpbmRvd3M6V2luZG93RHJhZ0xlYXZlXCIsXG5cdFx0V2luZG93RHJhZ092ZXI6IFwid2luZG93czpXaW5kb3dEcmFnT3ZlclwiLFxuXHR9LFxuXHRNYWM6IHtcblx0XHRBcHBsaWNhdGlvbkRpZEJlY29tZUFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUVmZmVjdGl2ZUFwcGVhcmFuY2VcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUljb246IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlSWNvblwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU2NyZWVuUGFyYW1ldGVyc1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uXCIsXG5cdFx0QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmc6IFwibWFjOkFwcGxpY2F0aW9uRGlkRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25EaWRIaWRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZEhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFJlc2lnbkFjdGl2ZU5vdGlmaWNhdGlvbjogXCJtYWM6QXBwbGljYXRpb25EaWRSZXNpZ25BY3RpdmVOb3RpZmljYXRpb25cIixcblx0XHRBcHBsaWNhdGlvbkRpZFVuaGlkZTogXCJtYWM6QXBwbGljYXRpb25EaWRVbmhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25EaWRVcGRhdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxCZWNvbWVBY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbEJlY29tZUFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEZpbmlzaExhdW5jaGluZzogXCJtYWM6QXBwbGljYXRpb25XaWxsRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsSGlkZTogXCJtYWM6QXBwbGljYXRpb25XaWxsSGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFJlc2lnbkFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVGVybWluYXRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxVbmhpZGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFVuaGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsVXBkYXRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZTogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZSFcIixcblx0XHRBcHBsaWNhdGlvblNob3VsZEhhbmRsZVJlb3BlbjogXCJtYWM6QXBwbGljYXRpb25TaG91bGRIYW5kbGVSZW9wZW4hXCIsXG5cdFx0V2luZG93RGlkQmVjb21lS2V5OiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dEaWRCZWNvbWVNYWluOiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVNYWluXCIsXG5cdFx0V2luZG93RGlkQmVnaW5TaGVldDogXCJtYWM6V2luZG93RGlkQmVnaW5TaGVldFwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUFscGhhOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VBbHBoYVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUJhY2tpbmdMb2NhdGlvbjogXCJtYWM6V2luZG93RGlkQ2hhbmdlQmFja2luZ0xvY2F0aW9uXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQmFja2luZ1Byb3BlcnRpZXM6IFwibWFjOldpbmRvd0RpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOldpbmRvd0RpZENoYW5nZU9jY2x1c2lvblN0YXRlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW46IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2U6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2VQcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5TcGFjZVByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTaGFyaW5nVHlwZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2hhcmluZ1R5cGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUaXRsZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVGl0bGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUb29sYmFyOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VUb29sYmFyXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd0RpZERlbWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dEaWRFbmRTaGVldDogXCJtYWM6V2luZG93RGlkRW5kU2hlZXRcIixcblx0XHRXaW5kb3dEaWRFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd0RpZEVudGVyRnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dEaWRFeGl0RnVsbFNjcmVlbjogXCJtYWM6V2luZG93RGlkRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEV4aXRWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd0RpZEV4cG9zZTogXCJtYWM6V2luZG93RGlkRXhwb3NlXCIsXG5cdFx0V2luZG93RGlkRm9jdXM6IFwibWFjOldpbmRvd0RpZEZvY3VzXCIsXG5cdFx0V2luZG93RGlkTWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJtYWM6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRPcmRlck9mZlNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd0RpZE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dEaWRSZXNpZ25LZXk6IFwibWFjOldpbmRvd0RpZFJlc2lnbktleVwiLFxuXHRcdFdpbmRvd0RpZFJlc2lnbk1haW46IFwibWFjOldpbmRvd0RpZFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwibWFjOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZTogXCJtYWM6V2luZG93RGlkVXBkYXRlXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd0RpZFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRpdGxlOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVRvb2xiYXJcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5XCIsXG5cdFx0V2luZG93U2hvdWxkQ2xvc2U6IFwibWFjOldpbmRvd1Nob3VsZENsb3NlIVwiLFxuXHRcdFdpbmRvd1dpbGxCZWNvbWVLZXk6IFwibWFjOldpbmRvd1dpbGxCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dXaWxsQmVjb21lTWFpbjogXCJtYWM6V2luZG93V2lsbEJlY29tZU1haW5cIixcblx0XHRXaW5kb3dXaWxsQmVnaW5TaGVldDogXCJtYWM6V2luZG93V2lsbEJlZ2luU2hlZXRcIixcblx0XHRXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93V2lsbENsb3NlOiBcIm1hYzpXaW5kb3dXaWxsQ2xvc2VcIixcblx0XHRXaW5kb3dXaWxsRGVtaW5pYXR1cml6ZTogXCJtYWM6V2luZG93V2lsbERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd1dpbGxFbnRlclZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEV4aXRGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyOiBcIm1hYzpXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsRm9jdXNcIixcblx0XHRXaW5kb3dXaWxsTWluaWF0dXJpemU6IFwibWFjOldpbmRvd1dpbGxNaW5pYXR1cml6ZVwiLFxuXHRcdFdpbmRvd1dpbGxNb3ZlOiBcIm1hYzpXaW5kb3dXaWxsTW92ZVwiLFxuXHRcdFdpbmRvd1dpbGxPcmRlck9mZlNjcmVlbjogXCJtYWM6V2luZG93V2lsbE9yZGVyT2ZmU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd1dpbGxPcmRlck9uU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbFJlc2lnbk1haW46IFwibWFjOldpbmRvd1dpbGxSZXNpZ25NYWluXCIsXG5cdFx0V2luZG93V2lsbFJlc2l6ZTogXCJtYWM6V2luZG93V2lsbFJlc2l6ZVwiLFxuXHRcdFdpbmRvd1dpbGxVbmZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsVW5mb2N1c1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVBbHBoYVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3I6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXM6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllc1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVTaGFkb3dcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlVGl0bGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVUb29sYmFyOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVG9vbGJhclwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd1dpbGxVc2VTdGFuZGFyZEZyYW1lOiBcIm1hYzpXaW5kb3dXaWxsVXNlU3RhbmRhcmRGcmFtZVwiLFxuXHRcdE1lbnVXaWxsT3BlbjogXCJtYWM6TWVudVdpbGxPcGVuXCIsXG5cdFx0TWVudURpZE9wZW46IFwibWFjOk1lbnVEaWRPcGVuXCIsXG5cdFx0TWVudURpZENsb3NlOiBcIm1hYzpNZW51RGlkQ2xvc2VcIixcblx0XHRNZW51V2lsbFNlbmRBY3Rpb246IFwibWFjOk1lbnVXaWxsU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVXaWxsSGlnaGxpZ2h0SXRlbTogXCJtYWM6TWVudVdpbGxIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudURpZEhpZ2hsaWdodEl0ZW06IFwibWFjOk1lbnVEaWRIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudVdpbGxEaXNwbGF5SXRlbTogXCJtYWM6TWVudVdpbGxEaXNwbGF5SXRlbVwiLFxuXHRcdE1lbnVEaWREaXNwbGF5SXRlbTogXCJtYWM6TWVudURpZERpc3BsYXlJdGVtXCIsXG5cdFx0TWVudVdpbGxBZGRJdGVtOiBcIm1hYzpNZW51V2lsbEFkZEl0ZW1cIixcblx0XHRNZW51RGlkQWRkSXRlbTogXCJtYWM6TWVudURpZEFkZEl0ZW1cIixcblx0XHRNZW51V2lsbFJlbW92ZUl0ZW06IFwibWFjOk1lbnVXaWxsUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVEaWRSZW1vdmVJdGVtOiBcIm1hYzpNZW51RGlkUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVXaWxsQmVnaW5UcmFja2luZzogXCJtYWM6TWVudVdpbGxCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudURpZEJlZ2luVHJhY2tpbmc6IFwibWFjOk1lbnVEaWRCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxFbmRUcmFja2luZzogXCJtYWM6TWVudVdpbGxFbmRUcmFja2luZ1wiLFxuXHRcdE1lbnVEaWRFbmRUcmFja2luZzogXCJtYWM6TWVudURpZEVuZFRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxVcGRhdGU6IFwibWFjOk1lbnVXaWxsVXBkYXRlXCIsXG5cdFx0TWVudURpZFVwZGF0ZTogXCJtYWM6TWVudURpZFVwZGF0ZVwiLFxuXHRcdE1lbnVXaWxsUG9wVXA6IFwibWFjOk1lbnVXaWxsUG9wVXBcIixcblx0XHRNZW51RGlkUG9wVXA6IFwibWFjOk1lbnVEaWRQb3BVcFwiLFxuXHRcdE1lbnVXaWxsU2VuZEFjdGlvblRvSXRlbTogXCJtYWM6TWVudVdpbGxTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0TWVudURpZFNlbmRBY3Rpb25Ub0l0ZW06IFwibWFjOk1lbnVEaWRTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0V2ViVmlld0RpZFN0YXJ0UHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkU3RhcnRQcm92aXNpb25hbE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZENvbW1pdE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRDb21taXROYXZpZ2F0aW9uXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZFwiLFxuXHRcdFdpbmRvd0ZpbGVEcmFnZ2luZ1BlcmZvcm1lZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nUGVyZm9ybWVkXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRXhpdGVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdFeGl0ZWRcIixcblx0fSxcblx0TGludXg6IHtcblx0XHRTeXN0ZW1UaGVtZUNoYW5nZWQ6IFwibGludXg6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdH0sXG5cdENvbW1vbjoge1xuXHRcdEFwcGxpY2F0aW9uU3RhcnRlZDogXCJjb21tb246QXBwbGljYXRpb25TdGFydGVkXCIsXG5cdFx0V2luZG93TWF4aW1pc2U6IFwiY29tbW9uOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJjb21tb246V2luZG93VW5NYXhpbWlzZVwiLFxuXHRcdFdpbmRvd0Z1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd0Z1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dVbkZ1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwiY29tbW9uOldpbmRvd1Jlc3RvcmVcIixcblx0XHRXaW5kb3dNaW5pbWlzZTogXCJjb21tb246V2luZG93TWluaW1pc2VcIixcblx0XHRXaW5kb3dVbk1pbmltaXNlOiBcImNvbW1vbjpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2luZzogXCJjb21tb246V2luZG93Q2xvc2luZ1wiLFxuXHRcdFdpbmRvd1pvb206IFwiY29tbW9uOldpbmRvd1pvb21cIixcblx0XHRXaW5kb3dab29tSW46IFwiY29tbW9uOldpbmRvd1pvb21JblwiLFxuXHRcdFdpbmRvd1pvb21PdXQ6IFwiY29tbW9uOldpbmRvd1pvb21PdXRcIixcblx0XHRXaW5kb3dab29tUmVzZXQ6IFwiY29tbW9uOldpbmRvd1pvb21SZXNldFwiLFxuXHRcdFdpbmRvd0ZvY3VzOiBcImNvbW1vbjpXaW5kb3dGb2N1c1wiLFxuXHRcdFdpbmRvd0xvc3RGb2N1czogXCJjb21tb246V2luZG93TG9zdEZvY3VzXCIsXG5cdFx0V2luZG93U2hvdzogXCJjb21tb246V2luZG93U2hvd1wiLFxuXHRcdFdpbmRvd0hpZGU6IFwiY29tbW9uOldpbmRvd0hpZGVcIixcblx0XHRXaW5kb3dEUElDaGFuZ2VkOiBcImNvbW1vbjpXaW5kb3dEUElDaGFuZ2VkXCIsXG5cdFx0V2luZG93RmlsZXNEcm9wcGVkOiBcImNvbW1vbjpXaW5kb3dGaWxlc0Ryb3BwZWRcIixcblx0XHRXaW5kb3dSdW50aW1lUmVhZHk6IFwiY29tbW9uOldpbmRvd1J1bnRpbWVSZWFkeVwiLFxuXHRcdFRoZW1lQ2hhbmdlZDogXCJjb21tb246VGhlbWVDaGFuZ2VkXCIsXG5cdH0sXG59O1xuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3BlbkZpbGVEaWFsb2dPcHRpb25zXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DaG9vc2VEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNob3Nlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZUZpbGVzXSAtIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ3JlYXRlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbU2hvd0hpZGRlbkZpbGVzXSAtIEluZGljYXRlcyBpZiBoaWRkZW4gZmlsZXMgc2hvdWxkIGJlIHNob3duLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbUmVzb2x2ZXNBbGlhc2VzXSAtIEluZGljYXRlcyBpZiBhbGlhc2VzIHNob3VsZCBiZSByZXNvbHZlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c011bHRpcGxlU2VsZWN0aW9uXSAtIEluZGljYXRlcyBpZiBtdWx0aXBsZSBzZWxlY3Rpb24gaXMgYWxsb3dlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0hpZGVFeHRlbnNpb25dIC0gSW5kaWNhdGVzIGlmIHRoZSBleHRlbnNpb24gc2hvdWxkIGJlIGhpZGRlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhblNlbGVjdEhpZGRlbkV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGV4dGVuc2lvbnMgY2FuIGJlIHNlbGVjdGVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZmlsZSBwYWNrYWdlcyBzaG91bGQgYmUgdHJlYXRlZCBhcyBkaXJlY3Rvcmllcy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c090aGVyRmlsZXR5cGVzXSAtIEluZGljYXRlcyBpZiBvdGhlciBmaWxlIHR5cGVzIGFyZSBhbGxvd2VkLlxuICogQHByb3BlcnR5IHtGaWxlRmlsdGVyW119IFtGaWx0ZXJzXSAtIEFycmF5IG9mIGZpbGUgZmlsdGVycy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGl0bGUgb2YgdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbTWVzc2FnZV0gLSBNZXNzYWdlIHRvIHNob3cgaW4gdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbQnV0dG9uVGV4dF0gLSBUZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRGlyZWN0b3J5XSAtIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtEZXRhY2hlZF0gLSBJbmRpY2F0ZXMgaWYgdGhlIGRpYWxvZyBzaG91bGQgYXBwZWFyIGRldGFjaGVkIGZyb20gdGhlIG1haW4gd2luZG93LlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBTYXZlRmlsZURpYWxvZ09wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRmlsZW5hbWVdIC0gRGVmYXVsdCBmaWxlbmFtZSB0byB1c2UgaW4gdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZURpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBkaXJlY3RvcmllcyBjYW4gYmUgY2hvc2VuLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ2hvb3NlRmlsZXNdIC0gSW5kaWNhdGVzIGlmIGZpbGVzIGNhbiBiZSBjaG9zZW4uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DcmVhdGVEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNyZWF0ZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtTaG93SGlkZGVuRmlsZXNdIC0gSW5kaWNhdGVzIGlmIGhpZGRlbiBmaWxlcyBzaG91bGQgYmUgc2hvd24uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtSZXNvbHZlc0FsaWFzZXNdIC0gSW5kaWNhdGVzIGlmIGFsaWFzZXMgc2hvdWxkIGJlIHJlc29sdmVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQWxsb3dzTXVsdGlwbGVTZWxlY3Rpb25dIC0gSW5kaWNhdGVzIGlmIG11bHRpcGxlIHNlbGVjdGlvbiBpcyBhbGxvd2VkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbSGlkZUV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgdGhlIGV4dGVuc2lvbiBzaG91bGQgYmUgaGlkZGVuLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuU2VsZWN0SGlkZGVuRXh0ZW5zaW9uXSAtIEluZGljYXRlcyBpZiBoaWRkZW4gZXh0ZW5zaW9ucyBjYW4gYmUgc2VsZWN0ZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtUcmVhdHNGaWxlUGFja2FnZXNBc0RpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBmaWxlIHBhY2thZ2VzIHNob3VsZCBiZSB0cmVhdGVkIGFzIGRpcmVjdG9yaWVzLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQWxsb3dzT3RoZXJGaWxldHlwZXNdIC0gSW5kaWNhdGVzIGlmIG90aGVyIGZpbGUgdHlwZXMgYXJlIGFsbG93ZWQuXG4gKiBAcHJvcGVydHkge0ZpbGVGaWx0ZXJbXX0gW0ZpbHRlcnNdIC0gQXJyYXkgb2YgZmlsZSBmaWx0ZXJzLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtUaXRsZV0gLSBUaXRsZSBvZiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtNZXNzYWdlXSAtIE1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtCdXR0b25UZXh0XSAtIFRleHQgdG8gZGlzcGxheSBvbiB0aGUgYnV0dG9uLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtEaXJlY3RvcnldIC0gRGlyZWN0b3J5IHRvIG9wZW4gaW4gdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0RldGFjaGVkXSAtIEluZGljYXRlcyBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cuXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBNZXNzYWdlRGlhbG9nT3B0aW9uc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IFtUaXRsZV0gLSBUaGUgdGl0bGUgb2YgdGhlIGRpYWxvZyB3aW5kb3cuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW01lc3NhZ2VdIC0gVGhlIG1haW4gbWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge0J1dHRvbltdfSBbQnV0dG9uc10gLSBBcnJheSBvZiBidXR0b24gb3B0aW9ucyB0byBzaG93IGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtEZXRhY2hlZF0gLSBUcnVlIGlmIHRoZSBkaWFsb2cgc2hvdWxkIGFwcGVhciBkZXRhY2hlZCBmcm9tIHRoZSBtYWluIHdpbmRvdyAoaWYgYXBwbGljYWJsZSkuXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBCdXR0b25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbTGFiZWxdIC0gVGV4dCB0aGF0IGFwcGVhcnMgd2l0aGluIHRoZSBidXR0b24uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtJc0NhbmNlbF0gLSBUcnVlIGlmIHRoZSBidXR0b24gc2hvdWxkIGNhbmNlbCBhbiBvcGVyYXRpb24gd2hlbiBjbGlja2VkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbSXNEZWZhdWx0XSAtIFRydWUgaWYgdGhlIGJ1dHRvbiBzaG91bGQgYmUgdGhlIGRlZmF1bHQgYWN0aW9uIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyBlbnRlci5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEZpbGVGaWx0ZXJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRGlzcGxheU5hbWVdIC0gRGlzcGxheSBuYW1lIGZvciB0aGUgZmlsdGVyLCBpdCBjb3VsZCBiZSBcIlRleHQgRmlsZXNcIiwgXCJJbWFnZXNcIiBldGMuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW1BhdHRlcm5dIC0gUGF0dGVybiB0byBtYXRjaCBmb3IgdGhlIGZpbHRlciwgZS5nLiBcIioudHh0OyoubWRcIiBmb3IgdGV4dCBtYXJrZG93biBmaWxlcy5cbiAqL1xuXG4vLyBzZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLmRpYWxvZ0Vycm9yQ2FsbGJhY2sgPSBkaWFsb2dFcnJvckNhbGxiYWNrO1xud2luZG93Ll93YWlscy5kaWFsb2dSZXN1bHRDYWxsYmFjayA9IGRpYWxvZ1Jlc3VsdENhbGxiYWNrO1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZC9ub24tc2VjdXJlJztcblxuLy8gRGVmaW5lIGNvbnN0YW50cyBmcm9tIHRoZSBgbWV0aG9kc2Agb2JqZWN0IGluIFRpdGxlIENhc2VcbmNvbnN0IERpYWxvZ0luZm8gPSAwO1xuY29uc3QgRGlhbG9nV2FybmluZyA9IDE7XG5jb25zdCBEaWFsb2dFcnJvciA9IDI7XG5jb25zdCBEaWFsb2dRdWVzdGlvbiA9IDM7XG5jb25zdCBEaWFsb2dPcGVuRmlsZSA9IDQ7XG5jb25zdCBEaWFsb2dTYXZlRmlsZSA9IDU7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkRpYWxvZywgJycpO1xuY29uc3QgZGlhbG9nUmVzcG9uc2VzID0gbmV3IE1hcCgpO1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBpZCB0aGF0IGlzIG5vdCBwcmVzZW50IGluIGRpYWxvZ1Jlc3BvbnNlcy5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IHVuaXF1ZSBpZFxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZUlEKCkge1xuICAgIGxldCByZXN1bHQ7XG4gICAgZG8ge1xuICAgICAgICByZXN1bHQgPSBuYW5vaWQoKTtcbiAgICB9IHdoaWxlIChkaWFsb2dSZXNwb25zZXMuaGFzKHJlc3VsdCkpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogU2hvd3MgYSBkaWFsb2cgb2Ygc3BlY2lmaWVkIHR5cGUgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0eXBlIC0gdHlwZSBvZiBkaWFsb2dcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN8T3BlbkZpbGVEaWFsb2dPcHRpb25zfFNhdmVGaWxlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIG9wdGlvbnMgZm9yIHRoZSBkaWFsb2dcbiAqIEByZXR1cm5zIHtQcm9taXNlfSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCByZXN1bHQgb2YgZGlhbG9nXG4gKi9cbmZ1bmN0aW9uIGRpYWxvZyh0eXBlLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBpZCA9IGdlbmVyYXRlSUQoKTtcbiAgICBvcHRpb25zW1wiZGlhbG9nLWlkXCJdID0gaWQ7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgZGlhbG9nUmVzcG9uc2VzLnNldChpZCwge3Jlc29sdmUsIHJlamVjdH0pO1xuICAgICAgICBjYWxsKHR5cGUsIG9wdGlvbnMpLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBIYW5kbGVzIHRoZSBjYWxsYmFjayBmcm9tIGEgZGlhbG9nLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFRoZSBJRCBvZiB0aGUgZGlhbG9nIHJlc3BvbnNlLlxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgLSBUaGUgZGF0YSByZWNlaXZlZCBmcm9tIHRoZSBkaWFsb2cuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGlzSlNPTiAtIEZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSBkYXRhIGlzIGluIEpTT04gZm9ybWF0LlxuICpcbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cbiAqL1xuZnVuY3Rpb24gZGlhbG9nUmVzdWx0Q2FsbGJhY2soaWQsIGRhdGEsIGlzSlNPTikge1xuICAgIGxldCBwID0gZGlhbG9nUmVzcG9uc2VzLmdldChpZCk7XG4gICAgaWYgKHApIHtcbiAgICAgICAgaWYgKGlzSlNPTikge1xuICAgICAgICAgICAgcC5yZXNvbHZlKEpTT04ucGFyc2UoZGF0YSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcC5yZXNvbHZlKGRhdGEpO1xuICAgICAgICB9XG4gICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBDYWxsYmFjayBmdW5jdGlvbiBmb3IgaGFuZGxpbmcgZXJyb3JzIGluIGRpYWxvZy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBUaGUgaWQgb2YgdGhlIGRpYWxvZyByZXNwb25zZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gZGlhbG9nRXJyb3JDYWxsYmFjayhpZCwgbWVzc2FnZSkge1xuICAgIGxldCBwID0gZGlhbG9nUmVzcG9uc2VzLmdldChpZCk7XG4gICAgaWYgKHApIHtcbiAgICAgICAgcC5yZWplY3QobWVzc2FnZSk7XG4gICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgIH1cbn1cblxuXG4vLyBSZXBsYWNlIGBtZXRob2RzYCB3aXRoIGNvbnN0YW50cyBpbiBUaXRsZSBDYXNlXG5cbi8qKlxuICogQHBhcmFtIHtNZXNzYWdlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcbiAqL1xuZXhwb3J0IGNvbnN0IEluZm8gPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ0luZm8sIG9wdGlvbnMpO1xuXG4vKipcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gLSBUaGUgbGFiZWwgb2YgdGhlIGJ1dHRvbiBwcmVzc2VkXG4gKi9cbmV4cG9ydCBjb25zdCBXYXJuaW5nID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dXYXJuaW5nLCBvcHRpb25zKTtcblxuLyoqXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gVGhlIGxhYmVsIG9mIHRoZSBidXR0b24gcHJlc3NlZFxuICovXG5leHBvcnQgY29uc3QgRXJyb3IgPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ0Vycm9yLCBvcHRpb25zKTtcblxuLyoqXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gVGhlIGxhYmVsIG9mIHRoZSBidXR0b24gcHJlc3NlZFxuICovXG5leHBvcnQgY29uc3QgUXVlc3Rpb24gPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ1F1ZXN0aW9uLCBvcHRpb25zKTtcblxuLyoqXG4gKiBAcGFyYW0ge09wZW5GaWxlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmdbXXxzdHJpbmc+fSBSZXR1cm5zIHNlbGVjdGVkIGZpbGUgb3IgbGlzdCBvZiBmaWxlcy4gUmV0dXJucyBibGFuayBzdHJpbmcgaWYgbm8gZmlsZSBpcyBzZWxlY3RlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IE9wZW5GaWxlID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dPcGVuRmlsZSwgb3B0aW9ucyk7XG5cbi8qKlxuICogQHBhcmFtIHtTYXZlRmlsZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gUmV0dXJucyB0aGUgc2VsZWN0ZWQgZmlsZS4gUmV0dXJucyBibGFuayBzdHJpbmcgaWYgbm8gZmlsZSBpcyBzZWxlY3RlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IFNhdmVGaWxlID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dTYXZlRmlsZSwgb3B0aW9ucyk7XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZVwiO1xuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSAnbmFub2lkL25vbi1zZWN1cmUnO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLmNhbGxSZXN1bHRIYW5kbGVyID0gcmVzdWx0SGFuZGxlcjtcbndpbmRvdy5fd2FpbHMuY2FsbEVycm9ySGFuZGxlciA9IGVycm9ySGFuZGxlcjtcblxuXG5jb25zdCBDYWxsQmluZGluZyA9IDA7XG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5DYWxsLCAnJyk7XG5sZXQgY2FsbFJlc3BvbnNlcyA9IG5ldyBNYXAoKTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgSUQgdXNpbmcgdGhlIG5hbm9pZCBsaWJyYXJ5LlxuICpcbiAqIEByZXR1cm4ge3N0cmluZ30gLSBBIHVuaXF1ZSBJRCB0aGF0IGRvZXMgbm90IGV4aXN0IGluIHRoZSBjYWxsUmVzcG9uc2VzIHNldC5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVJRCgpIHtcbiAgICBsZXQgcmVzdWx0O1xuICAgIGRvIHtcbiAgICAgICAgcmVzdWx0ID0gbmFub2lkKCk7XG4gICAgfSB3aGlsZSAoY2FsbFJlc3BvbnNlcy5oYXMocmVzdWx0KSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBIYW5kbGVzIHRoZSByZXN1bHQgb2YgYSBjYWxsIHJlcXVlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSByZXF1ZXN0IHRvIGhhbmRsZSB0aGUgcmVzdWx0IGZvci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhIC0gVGhlIHJlc3VsdCBkYXRhIG9mIHRoZSByZXF1ZXN0LlxuICogQHBhcmFtIHtib29sZWFufSBpc0pTT04gLSBJbmRpY2F0ZXMgd2hldGhlciB0aGUgZGF0YSBpcyBKU09OIG9yIG5vdC5cbiAqXG4gKiBAcmV0dXJuIHt1bmRlZmluZWR9IC0gVGhpcyBtZXRob2QgZG9lcyBub3QgcmV0dXJuIGFueSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gcmVzdWx0SGFuZGxlcihpZCwgZGF0YSwgaXNKU09OKSB7XG4gICAgY29uc3QgcHJvbWlzZUhhbmRsZXIgPSBnZXRBbmREZWxldGVSZXNwb25zZShpZCk7XG4gICAgaWYgKHByb21pc2VIYW5kbGVyKSB7XG4gICAgICAgIHByb21pc2VIYW5kbGVyLnJlc29sdmUoaXNKU09OID8gSlNPTi5wYXJzZShkYXRhKSA6IGRhdGEpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBIYW5kbGVzIHRoZSBlcnJvciBmcm9tIGEgY2FsbCByZXF1ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFRoZSBpZCBvZiB0aGUgcHJvbWlzZSBoYW5kbGVyLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBUaGUgZXJyb3IgbWVzc2FnZSB0byByZWplY3QgdGhlIHByb21pc2UgaGFuZGxlciB3aXRoLlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGVycm9ySGFuZGxlcihpZCwgbWVzc2FnZSkge1xuICAgIGNvbnN0IHByb21pc2VIYW5kbGVyID0gZ2V0QW5kRGVsZXRlUmVzcG9uc2UoaWQpO1xuICAgIGlmIChwcm9taXNlSGFuZGxlcikge1xuICAgICAgICBwcm9taXNlSGFuZGxlci5yZWplY3QobWVzc2FnZSk7XG4gICAgfVxufVxuXG4vKipcbiAqIFJldHJpZXZlcyBhbmQgcmVtb3ZlcyB0aGUgcmVzcG9uc2UgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBJRCBmcm9tIHRoZSBjYWxsUmVzcG9uc2VzIG1hcC5cbiAqXG4gKiBAcGFyYW0ge2FueX0gaWQgLSBUaGUgSUQgb2YgdGhlIHJlc3BvbnNlIHRvIGJlIHJldHJpZXZlZCBhbmQgcmVtb3ZlZC5cbiAqXG4gKiBAcmV0dXJucyB7YW55fSBUaGUgcmVzcG9uc2Ugb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gSUQuXG4gKi9cbmZ1bmN0aW9uIGdldEFuZERlbGV0ZVJlc3BvbnNlKGlkKSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBjYWxsUmVzcG9uc2VzLmdldChpZCk7XG4gICAgY2FsbFJlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgIHJldHVybiByZXNwb25zZTtcbn1cblxuLyoqXG4gKiBFeGVjdXRlcyBhIGNhbGwgdXNpbmcgdGhlIHByb3ZpZGVkIHR5cGUgYW5kIG9wdGlvbnMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSB0eXBlIC0gVGhlIHR5cGUgb2YgY2FsbCB0byBleGVjdXRlLlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSAtIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIGNhbGwuXG4gKiBAcmV0dXJuIHtQcm9taXNlfSAtIEEgcHJvbWlzZSB0aGF0IHdpbGwgYmUgcmVzb2x2ZWQgb3IgcmVqZWN0ZWQgYmFzZWQgb24gdGhlIHJlc3VsdCBvZiB0aGUgY2FsbC5cbiAqL1xuZnVuY3Rpb24gY2FsbEJpbmRpbmcodHlwZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY29uc3QgaWQgPSBnZW5lcmF0ZUlEKCk7XG4gICAgICAgIG9wdGlvbnNbXCJjYWxsLWlkXCJdID0gaWQ7XG4gICAgICAgIGNhbGxSZXNwb25zZXMuc2V0KGlkLCB7IHJlc29sdmUsIHJlamVjdCB9KTtcbiAgICAgICAgY2FsbCh0eXBlLCBvcHRpb25zKS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICBjYWxsUmVzcG9uc2VzLmRlbGV0ZShpZCk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIENhbGwgbWV0aG9kLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgZm9yIHRoZSBtZXRob2QuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSAtIFRoZSByZXN1bHQgb2YgdGhlIGNhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDYWxsKG9wdGlvbnMpIHtcbiAgICByZXR1cm4gY2FsbEJpbmRpbmcoQ2FsbEJpbmRpbmcsIG9wdGlvbnMpO1xufVxuXG4vKipcbiAqIEV4ZWN1dGVzIGEgbWV0aG9kIGJ5IG5hbWUuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIGluIHRoZSBmb3JtYXQgJ3BhY2thZ2Uuc3RydWN0Lm1ldGhvZCcuXG4gKiBAcGFyYW0gey4uLip9IGFyZ3MgLSBUaGUgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIG1ldGhvZC5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgbmFtZSBpcyBub3QgYSBzdHJpbmcgb3IgaXMgbm90IGluIHRoZSBjb3JyZWN0IGZvcm1hdC5cbiAqIEByZXR1cm5zIHsqfSBUaGUgcmVzdWx0IG9mIHRoZSBtZXRob2QgZXhlY3V0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQnlOYW1lKG5hbWUsIC4uLmFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIG5hbWUgIT09IFwic3RyaW5nXCIgfHwgbmFtZS5zcGxpdChcIi5cIikubGVuZ3RoICE9PSAzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbGxCeU5hbWUgcmVxdWlyZXMgYSBzdHJpbmcgaW4gdGhlIGZvcm1hdCAncGFja2FnZS5zdHJ1Y3QubWV0aG9kJ1wiKTtcbiAgICB9XG4gICAgbGV0IFtwYWNrYWdlTmFtZSwgc3RydWN0TmFtZSwgbWV0aG9kTmFtZV0gPSBuYW1lLnNwbGl0KFwiLlwiKTtcbiAgICByZXR1cm4gY2FsbEJpbmRpbmcoQ2FsbEJpbmRpbmcsIHtcbiAgICAgICAgcGFja2FnZU5hbWUsXG4gICAgICAgIHN0cnVjdE5hbWUsXG4gICAgICAgIG1ldGhvZE5hbWUsXG4gICAgICAgIGFyZ3NcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBDYWxscyBhIG1ldGhvZCBieSBpdHMgSUQgd2l0aCB0aGUgc3BlY2lmaWVkIGFyZ3VtZW50cy5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gbWV0aG9kSUQgLSBUaGUgSUQgb2YgdGhlIG1ldGhvZCB0byBjYWxsLlxuICogQHBhcmFtIHsuLi4qfSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXG4gKiBAcmV0dXJuIHsqfSAtIFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQnlJRChtZXRob2RJRCwgLi4uYXJncykge1xuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywge1xuICAgICAgICBtZXRob2RJRCxcbiAgICAgICAgYXJnc1xuICAgIH0pO1xufVxuXG4vKipcbiAqIENhbGxzIGEgbWV0aG9kIG9uIGEgcGx1Z2luLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwbHVnaW5OYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHBsdWdpbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2ROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIG1ldGhvZCB0byBjYWxsLlxuICogQHBhcmFtIHsuLi4qfSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXG4gKiBAcmV0dXJucyB7Kn0gLSBUaGUgcmVzdWx0IG9mIHRoZSBtZXRob2QgY2FsbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFBsdWdpbihwbHVnaW5OYW1lLCBtZXRob2ROYW1lLCAuLi5hcmdzKSB7XG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XG4gICAgICAgIHBhY2thZ2VOYW1lOiBcIndhaWxzLXBsdWdpbnNcIixcbiAgICAgICAgc3RydWN0TmFtZTogcGx1Z2luTmFtZSxcbiAgICAgICAgbWV0aG9kTmFtZSxcbiAgICAgICAgYXJnc1xuICAgIH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQge2RlYnVnTG9nfSBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvbG9nXCI7XG5cbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xuXG5pbXBvcnQgKiBhcyBBcHBsaWNhdGlvbiBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb25cIjtcbmltcG9ydCAqIGFzIEJyb3dzZXIgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXJcIjtcbmltcG9ydCAqIGFzIENsaXBib2FyZCBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvY2xpcGJvYXJkXCI7XG5pbXBvcnQgKiBhcyBDb250ZXh0TWVudSBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvY29udGV4dG1lbnVcIjtcbmltcG9ydCAqIGFzIERyYWcgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RyYWdcIjtcbmltcG9ydCAqIGFzIEZsYWdzIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9mbGFnc1wiO1xuaW1wb3J0ICogYXMgU2NyZWVucyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvc2NyZWVuc1wiO1xuaW1wb3J0ICogYXMgU3lzdGVtIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9zeXN0ZW1cIjtcbmltcG9ydCAqIGFzIFdpbmRvdyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvd2luZG93XCI7XG5pbXBvcnQgKiBhcyBXTUwgZnJvbSAnLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvd21sJztcbmltcG9ydCAqIGFzIEV2ZW50cyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZXZlbnRzXCI7XG5pbXBvcnQgKiBhcyBEaWFsb2dzIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9kaWFsb2dzXCI7XG5pbXBvcnQgKiBhcyBDYWxsIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxsc1wiO1xuaW1wb3J0IHtpbnZva2V9IGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9zeXN0ZW1cIjtcblxuLyoqKlxuIFRoaXMgdGVjaG5pcXVlIGZvciBwcm9wZXIgbG9hZCBkZXRlY3Rpb24gaXMgdGFrZW4gZnJvbSBIVE1YOlxuXG4gQlNEIDItQ2xhdXNlIExpY2Vuc2VcblxuIENvcHlyaWdodCAoYykgMjAyMCwgQmlnIFNreSBTb2Z0d2FyZVxuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cbiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXRcbiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuIDEuIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuXG4gMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiXG4gQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRVxuIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEVcbiBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTFxuIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SXG4gU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVJcbiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLFxuIE9SIFRPUlQgKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFXG4gT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cblxuICoqKi9cblxud2luZG93Ll93YWlscy5pbnZva2U9aW52b2tlO1xuXG53aW5kb3cud2FpbHMgPSB3aW5kb3cud2FpbHMgfHwge307XG53aW5kb3cud2FpbHMuQXBwbGljYXRpb24gPSBBcHBsaWNhdGlvbjtcbndpbmRvdy53YWlscy5Ccm93c2VyID0gQnJvd3NlcjtcbndpbmRvdy53YWlscy5DYWxsID0gQ2FsbDtcbndpbmRvdy53YWlscy5DbGlwYm9hcmQgPSBDbGlwYm9hcmQ7XG53aW5kb3cud2FpbHMuRGlhbG9ncyA9IERpYWxvZ3M7XG53aW5kb3cud2FpbHMuRXZlbnRzID0gRXZlbnRzO1xud2luZG93LndhaWxzLkZsYWdzID0gRmxhZ3M7XG53aW5kb3cud2FpbHMuU2NyZWVucyA9IFNjcmVlbnM7XG53aW5kb3cud2FpbHMuU3lzdGVtID0gU3lzdGVtO1xud2luZG93LndhaWxzLldpbmRvdyA9IFdpbmRvdztcbndpbmRvdy53YWlscy5XTUwgPSBXTUw7XG5cblxubGV0IGlzUmVhZHkgPSBmYWxzZVxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGZ1bmN0aW9uKCkge1xuICAgIGlzUmVhZHkgPSB0cnVlXG4gICAgd2luZG93Ll93YWlscy5pbnZva2UoJ3dhaWxzOnJ1bnRpbWU6cmVhZHknKTtcbiAgICBpZihERUJVRykge1xuICAgICAgICBkZWJ1Z0xvZyhcIldhaWxzIFJ1bnRpbWUgTG9hZGVkXCIpO1xuICAgIH1cbn0pXG5cbmZ1bmN0aW9uIHdoZW5SZWFkeShmbikge1xuICAgIGlmIChpc1JlYWR5IHx8IGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdjb21wbGV0ZScpIHtcbiAgICAgICAgZm4oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZm4pO1xuICAgIH1cbn1cblxud2hlblJlYWR5KCgpID0+IHtcbiAgICBXTUwuUmVsb2FkKCk7XG59KTtcbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7O0FBS08sV0FBUyxTQUFTLFNBQVM7QUFFOUIsWUFBUTtBQUFBLE1BQ0osa0JBQWtCLFVBQVU7QUFBQSxNQUM1QjtBQUFBLE1BQ0E7QUFBQSxJQUNKO0FBQUEsRUFDSjs7O0FDWkE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7QUNBQSxNQUFJLGNBQ0Y7QUFXSyxNQUFJLFNBQVMsQ0FBQ0EsUUFBTyxPQUFPO0FBQ2pDLFFBQUksS0FBSztBQUNULFFBQUksSUFBSUE7QUFDUixXQUFPLEtBQUs7QUFDVixZQUFNLFlBQWEsS0FBSyxPQUFPLElBQUksS0FBTSxDQUFDO0FBQUEsSUFDNUM7QUFDQSxXQUFPO0FBQUEsRUFDVDs7O0FDTkEsTUFBTSxhQUFhLE9BQU8sU0FBUyxTQUFTO0FBR3JDLE1BQU0sY0FBYztBQUFBLElBQ3ZCLE1BQU07QUFBQSxJQUNOLFdBQVc7QUFBQSxJQUNYLGFBQWE7QUFBQSxJQUNiLFFBQVE7QUFBQSxJQUNSLGFBQWE7QUFBQSxJQUNiLFFBQVE7QUFBQSxJQUNSLFFBQVE7QUFBQSxJQUNSLFNBQVM7QUFBQSxJQUNULFFBQVE7QUFBQSxJQUNSLFNBQVM7QUFBQSxFQUNiO0FBQ08sTUFBSSxXQUFXLE9BQU87QUFzQnRCLFdBQVMsdUJBQXVCLFFBQVEsWUFBWTtBQUN2RCxXQUFPLFNBQVUsUUFBUSxPQUFLLE1BQU07QUFDaEMsYUFBTyxrQkFBa0IsUUFBUSxRQUFRLFlBQVksSUFBSTtBQUFBLElBQzdEO0FBQUEsRUFDSjtBQXFDQSxXQUFTLGtCQUFrQixVQUFVLFFBQVEsWUFBWSxNQUFNO0FBQzNELFFBQUksTUFBTSxJQUFJLElBQUksVUFBVTtBQUM1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QXdCO0FBQUEsTUFDeEIsbUJBQW1CO0FBQUEsTUFDbkIsMEJBQTBCO0FBQUEsTUFDMUIsOEJBQThCO0FBQUEsTUFDOUIseUJBQXlCO0FBQUEsTUFDekIsNkJBQTZCO0FBQUEsTUFDN0IsaUJBQWlCO0FBQUEsTUFDakIsZ0JBQWdCO0FBQUEsTUFDaEIsc0JBQXNCO0FBQUEsTUFDdEIsZUFBZTtBQUFBLE1BQ2YseUJBQXlCO0FBQUEsTUFDekIsd0JBQXdCO0FBQUEsTUFDeEIsb0JBQW9CO0FBQUEsTUFDcEIscUJBQXFCO0FBQUEsTUFDckIsaUJBQWlCO0FBQUEsTUFDakIsaUJBQWlCO0FBQUEsTUFDakIsc0JBQXNCO0FBQUEsTUFDdEIsbUNBQW1DO0FBQUEsTUFDbkMscUNBQXFDO0FBQUEsTUFDckMsdUJBQXVCO0FBQUEsTUFDdkIsc0JBQXNCO0FBQUEsTUFDdEIsd0JBQXdCO0FBQUEsTUFDeEIsMkJBQTJCO0FBQUEsTUFDM0IsbUJBQW1CO0FBQUEsTUFDbkIscUJBQXFCO0FBQUEsTUFDckIsc0JBQXNCO0FBQUEsTUFDdEIsc0JBQXNCO0FBQUEsTUFDdEIsOEJBQThCO0FBQUEsTUFDOUIsaUJBQWlCO0FBQUEsTUFDakIseUJBQXlCO0FBQUEsTUFDekIsMkJBQTJCO0FBQUEsTUFDM0IsK0JBQStCO0FBQUEsTUFDL0IsMEJBQTBCO0FBQUEsTUFDMUIsOEJBQThCO0FBQUEsTUFDOUIsaUJBQWlCO0FBQUEsTUFDakIsdUJBQXVCO0FBQUEsTUFDdkIsZ0JBQWdCO0FBQUEsTUFDaEIsMEJBQTBCO0FBQUEsTUFDMUIseUJBQXlCO0FBQUEsTUFDekIsc0JBQXNCO0FBQUEsTUFDdEIsa0JBQWtCO0FBQUEsTUFDbEIsbUJBQW1CO0FBQUEsTUFDbkIsa0JBQWtCO0FBQUEsTUFDbEIsdUJBQXVCO0FBQUEsTUFDdkIsb0NBQW9DO0FBQUEsTUFDcEMsc0NBQXNDO0FBQUEsTUFDdEMsd0JBQXdCO0FBQUEsTUFDeEIsdUJBQXVCO0FBQUEsTUFDdkIseUJBQXlCO0FBQUEsTUFDekIsNEJBQTRCO0FBQUEsTUFDNUIsNEJBQTRC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QUFTLFlBQVksS0FBSyxNQUFNLEdBQUcsRUFBRSxXQUFXLEdBQUc7QUFDMUQsWUFBTSxJQUFJLE1BQU0sb0VBQW9FO0FBQUEsSUFDeEY7QUFDQSxRQUFJLENBQUMsYUFBYSxZQUFZLFVBQVUsSUFBSSxLQUFLLE1BQU0sR0FBRztBQUMxRCxXQUFPLFlBQVksYUFBYTtBQUFBLE1BQzVCO0FBQUEsTUFDQTtBQUFBLE1BQ0E7QUFBQSxNQUNBO0FBQUEsSUFDSixDQUFDO0FBQUEsRUFDTDtBQVNPLFdBQVMsS0FBSyxhQUFhLE1BQU07QUFDcEMsV0FBTyxZQUFZLGFBQWE7QUFBQSxNQUM1QjtBQUFBLE1BQ0E7QUFBQSxJQUNKLENBQUM7QUFBQSxFQUNMO0FBVU8sV0FBUyxPQUFPLFlBQVksZUFBZSxNQUFNO0FBQ3BELFdBQU8sWUFBWSxhQUFhO0FBQUEsTUFDNUIsYUFBYTtBQUFBLE1BQ2IsWUFBWTtBQUFBLE1BQ1o7QUFBQSxNQUNBO0FBQUEsSUFDSixDQUFDO0FBQUEsRUFDTDs7O0FDcEpBLFNBQU8sU0FBUyxPQUFPLFVBQVUsQ0FBQztBQWdEbEMsU0FBTyxPQUFPLFNBQU87QUFFckIsU0FBTyxRQUFRLE9BQU8sU0FBUyxDQUFDO0FBQ2hDLFNBQU8sTUFBTSxjQUFjO0FBQzNCLFNBQU8sTUFBTSxVQUFVO0FBQ3ZCLFNBQU8sTUFBTSxPQUFPO0FBQ3BCLFNBQU8sTUFBTSxZQUFZO0FBQ3pCLFNBQU8sTUFBTSxVQUFVO0FBQ3ZCLFNBQU8sTUFBTSxTQUFTO0FBQ3RCLFNBQU8sTUFBTSxRQUFRO0FBQ3JCLFNBQU8sTUFBTSxVQUFVO0FBQ3ZCLFNBQU8sTUFBTSxTQUFTO0FBQ3RCLFNBQU8sTUFBTSxTQUFTO0FBQ3RCLFNBQU8sTUFBTSxNQUFNO0FBR25CLE1BQUksVUFBVTtBQUNkLFdBQVMsaUJBQWlCLG9CQUFvQixXQUFXO0FBQ3JELGNBQVU7QUFDVixXQUFPLE9BQU8sT0FBTyxxQkFBcUI7QUFDMUMsUUFBRyxNQUFPO0FBQ04sZUFBUyxzQkFBc0I7QUFBQSxJQUNuQztBQUFBLEVBQ0osQ0FBQztBQUVELFdBQVMsVUFBVSxJQUFJO0FBQ25CLFFBQUksV0FBVyxTQUFTLGVBQWUsWUFBWTtBQUMvQyxTQUFHO0FBQUEsSUFDUCxPQUFPO0FBQ0gsZUFBUyxpQkFBaUIsb0JBQW9CLEVBQUU7QUFBQSxJQUNwRDtBQUFBLEVBQ0o7QUFFQSxZQUFVLE1BQU07QUFDWixJQUFJLE9BQU87QUFBQSxFQUNmLENBQUM7IiwKICAibmFtZXMiOiBbInNpemUiLCAiY2FsbCIsICJjYWxsIiwgImNhbGwiLCAiY2FsbCIsICJjYWxsIiwgIkhpZGUiLCAiU2hvdyIsICJzZXRSZXNpemFibGUiLCAiY2FsbCIsICJ3aWR0aCIsICJoZWlnaHQiLCAicmVzaXphYmxlIiwgIkhpZGUiLCAiU2hvdyIsICJjYWxsIiwgImV2ZW50TmFtZSIsICJFcnJvciIsICJjYWxsIiwgIkVycm9yIiwgImNhbGwiLCAiZ2VuZXJhdGVJRCJdCn0K diff --git a/v3/internal/runtime/Taskfile.yaml b/v3/internal/runtime/Taskfile.yaml index c16c2d43945..85a9d2c25de 100644 --- a/v3/internal/runtime/Taskfile.yaml +++ b/v3/internal/runtime/Taskfile.yaml @@ -36,6 +36,7 @@ tasks: cmds: - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/frameless/assets/runtime.js + - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/window-api/assets/runtime.js - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/wml/assets/runtime.js - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../internal/commands/build_assets/runtime/runtime.js - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../pkg/application/assets/alpha/runtime.js @@ -50,4 +51,4 @@ tasks: generate:events: dir: ../../tasks/events cmds: - - go run generate.go \ No newline at end of file + - go run generate.go diff --git a/v3/pkg/application/messageprocessor.go b/v3/pkg/application/messageprocessor.go index d9a8e685878..de8b9ac4e19 100644 --- a/v3/pkg/application/messageprocessor.go +++ b/v3/pkg/application/messageprocessor.go @@ -12,16 +12,16 @@ import ( // as parameter through every function call. const ( - callRequest int = 0 - clipboardRequest = 1 - applicationRequest = 2 - eventsRequest = 3 - contextMenuRequest = 4 - dialogRequest = 5 - windowRequest = 6 - screensRequest = 7 - systemRequest = 8 - browserRequest = 9 + callRequest = 0 + clipboardRequest = 1 + applicationRequest = 2 + eventsRequest = 3 + contextMenuRequest = 4 + dialogRequest = 5 + windowRequest = 6 + screensRequest = 7 + systemRequest = 8 + browserRequest = 9 ) type MessageProcessor struct { diff --git a/v3/pkg/application/messageprocessor_window.go b/v3/pkg/application/messageprocessor_window.go index aa69a9e77ff..1e5f12f0c32 100644 --- a/v3/pkg/application/messageprocessor_window.go +++ b/v3/pkg/application/messageprocessor_window.go @@ -123,6 +123,9 @@ func (m *MessageProcessor) processWindowMethod(method int, rw http.ResponseWrite case WindowUnMaximise: window.UnMaximise() m.ok(rw) + case WindowToggleMaximise: + window.ToggleMaximise() + m.ok(rw) case WindowRestore: window.Restore() m.ok(rw) diff --git a/v3/pkg/application/webview_window.go b/v3/pkg/application/webview_window.go index 63f9a4a6836..84b57d1659d 100644 --- a/v3/pkg/application/webview_window.go +++ b/v3/pkg/application/webview_window.go @@ -803,6 +803,20 @@ func (w *WebviewWindow) ToggleFullscreen() { }) } +// ToggleMaximise toggles the window between maximised and normal +func (w *WebviewWindow) ToggleMaximise() { + if w.impl == nil && !w.isDestroyed() { + return + } + InvokeSync(func() { + if w.IsMaximised() { + w.UnMaximise() + } else { + w.Maximise() + } + }) +} + func (w *WebviewWindow) ToggleDevTools() { if w.impl == nil && !w.isDestroyed() { return diff --git a/v3/pkg/application/window.go b/v3/pkg/application/window.go index 46a8420cc7c..2398cd3682b 100644 --- a/v3/pkg/application/window.go +++ b/v3/pkg/application/window.go @@ -67,6 +67,7 @@ type Window interface { Size() (width int, height int) ToggleDevTools() ToggleFullscreen() + ToggleMaximise() UnFullscreen() UnMaximise() UnMinimise() diff --git a/v3/plugins/experimental/server/window.go b/v3/plugins/experimental/server/window.go index 7348d456f0e..9c50f6ff9f5 100644 --- a/v3/plugins/experimental/server/window.go +++ b/v3/plugins/experimental/server/window.go @@ -217,6 +217,8 @@ func (w Window) ToggleDevTools() { func (w Window) ToggleFullscreen() {} +func (w Window) ToggleMaximise() {} + func (w Window) UnFullscreen() {} func (w Window) UnMaximise() {} From 3bf4ea5113636ff28c804a99763b30bd632ea46e Mon Sep 17 00:00:00 2001 From: madflow Date: Wed, 28 Feb 2024 22:46:33 +0100 Subject: [PATCH 041/369] fix: json5 code highlighting (#3278) --- website/docusaurus.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 0c3f91edbab..737218f07a3 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -253,6 +253,7 @@ module.exports = async function configCreatorAsync() { prism: { theme: lightCodeTheme, darkTheme: darkCodeTheme, + additionalLanguages: ["json5"], }, colorMode: { defaultMode: "light", From a9c22f058881867d12fca5a4b052c516d33d5461 Mon Sep 17 00:00:00 2001 From: 5aaee9 <7685264+5aaee9@users.noreply.github.com> Date: Thu, 29 Feb 2024 05:47:25 +0800 Subject: [PATCH 042/369] fix: wrong baseURL if open window twice (#3273) --- mkdocs-website/docs/en/changelog.md | 1 + v3/internal/assetserver/assetserver.go | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/mkdocs-website/docs/en/changelog.md b/mkdocs-website/docs/en/changelog.md index 8ea0a236c48..5cc3cb3898f 100644 --- a/mkdocs-website/docs/en/changelog.md +++ b/mkdocs-website/docs/en/changelog.md @@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix replace line in `go.mod` to use relative paths. Fixes Windows paths with spaces - @leaanthony. - Fix MacOS systray click handling when no attached window by [thomas-senechal](https://github.com/thomas-senechal) in PR [#3207](https://github.com/wailsapp/wails/pull/3207) - Fix failing Windows build due to unknown option by [thomas-senechal](https://github.com/thomas-senechal) in PR [#3208](https://github.com/wailsapp/wails/pull/3208) +- Fix wrong baseURL when open window twice by @5aaee9 in PR [#3273](https://github.com/wailsapp/wails/pull/3273) ### Changed diff --git a/v3/internal/assetserver/assetserver.go b/v3/internal/assetserver/assetserver.go index 4acddcddf3e..0d80007e763 100644 --- a/v3/internal/assetserver/assetserver.go +++ b/v3/internal/assetserver/assetserver.go @@ -7,7 +7,6 @@ import ( "net/http" "net/http/httptest" "net/url" - "path" "strings" "time" ) @@ -160,8 +159,7 @@ func GetStartURL(userURL string) (string, error) { return "", fmt.Errorf("Error parsing URL: " + err.Error()) } if parsedURL.Scheme == "" { - baseURL.Path = path.Join(baseURL.Path, userURL) - startURL = baseURL.String() + startURL = baseURL.ResolveReference(&url.URL{Path: userURL}).String() // if the original URL had a trailing slash, add it back if strings.HasSuffix(userURL, "/") && !strings.HasSuffix(startURL, "/") { startURL = startURL + "/" From e714dd92a84bf9324bbcb3ac839e98083f960821 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 2 Mar 2024 15:34:49 +1100 Subject: [PATCH 043/369] chore: update sponsors.svg (#3291) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index 1538fec3739..fc6897ba73d 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -118,7 +118,11 @@ text { - + + + + + Helpers From 5d22da412640906439df85cd96b00548f7dbd35f Mon Sep 17 00:00:00 2001 From: Cristian Bilu Date: Sat, 2 Mar 2024 06:47:59 +0200 Subject: [PATCH 044/369] Add disable zoom on mac (#3289) * Add disable zoom on mac * Add changelog line * Add zommable in main.m I see this file is ignore, but i think it's better to keep it up-to-date so if we ever unignore it will work correctly. --- v2/internal/frontend/desktop/darwin/Application.h | 2 +- v2/internal/frontend/desktop/darwin/Application.m | 4 ++-- v2/internal/frontend/desktop/darwin/WailsContext.h | 2 +- v2/internal/frontend/desktop/darwin/WailsContext.m | 7 +++++-- v2/internal/frontend/desktop/darwin/main.m | 3 ++- v2/internal/frontend/desktop/darwin/window.go | 6 ++++-- v2/pkg/options/mac/mac.go | 1 + website/src/pages/changelog.mdx | 1 + .../versioned_docs/version-v2.8.0/reference/options.mdx | 8 ++++++++ 9 files changed, 25 insertions(+), 9 deletions(-) diff --git a/v2/internal/frontend/desktop/darwin/Application.h b/v2/internal/frontend/desktop/darwin/Application.h index eb679f3b5eb..5c4f2fe91a2 100644 --- a/v2/internal/frontend/desktop/darwin/Application.h +++ b/v2/internal/frontend/desktop/darwin/Application.h @@ -17,7 +17,7 @@ #define WindowStartsMinimised 2 #define WindowStartsFullscreen 3 -WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceEnabled, const char* singleInstanceUniqueId); +WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int zoomable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceEnabled, const char* singleInstanceUniqueId); void Run(void*, const char* url); void SetTitle(void* ctx, const char *title); diff --git a/v2/internal/frontend/desktop/darwin/Application.m b/v2/internal/frontend/desktop/darwin/Application.m index c428b4ce628..f0a5a2a9ac6 100644 --- a/v2/internal/frontend/desktop/darwin/Application.m +++ b/v2/internal/frontend/desktop/darwin/Application.m @@ -14,7 +14,7 @@ #import "WailsMenu.h" #import "WailsMenuItem.h" -WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceLockEnabled, const char* singleInstanceUniqueId) { +WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int zoomable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceLockEnabled, const char* singleInstanceUniqueId) { [NSApplication sharedApplication]; @@ -27,7 +27,7 @@ fullscreen = 1; } - [result CreateWindow:width :height :frameless :resizable :fullscreen :fullSizeContent :hideTitleBar :titlebarAppearsTransparent :hideTitle :useToolbar :hideToolbarSeparator :webviewIsTransparent :hideWindowOnClose :safeInit(appearance) :windowIsTranslucent :minWidth :minHeight :maxWidth :maxHeight :fraudulentWebsiteWarningEnabled :preferences]; + [result CreateWindow:width :height :frameless :resizable :zoomable :fullscreen :fullSizeContent :hideTitleBar :titlebarAppearsTransparent :hideTitle :useToolbar :hideToolbarSeparator :webviewIsTransparent :hideWindowOnClose :safeInit(appearance) :windowIsTranslucent :minWidth :minHeight :maxWidth :maxHeight :fraudulentWebsiteWarningEnabled :preferences]; [result SetTitle:safeInit(title)]; [result Center]; diff --git a/v2/internal/frontend/desktop/darwin/WailsContext.h b/v2/internal/frontend/desktop/darwin/WailsContext.h index ab5e5c2a201..0e83ff0a8fa 100644 --- a/v2/internal/frontend/desktop/darwin/WailsContext.h +++ b/v2/internal/frontend/desktop/darwin/WailsContext.h @@ -64,7 +64,7 @@ struct Preferences { bool *fullscreenEnabled; }; -- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString *)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight :(bool)fraudulentWebsiteWarningEnabled :(struct Preferences)preferences; +- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)zoomable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString *)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight :(bool)fraudulentWebsiteWarningEnabled :(struct Preferences)preferences; - (void) SetSize:(int)width :(int)height; - (void) SetPosition:(int)x :(int) y; - (void) SetMinSize:(int)minWidth :(int)minHeight; diff --git a/v2/internal/frontend/desktop/darwin/WailsContext.m b/v2/internal/frontend/desktop/darwin/WailsContext.m index fd15465a836..13af17f6023 100644 --- a/v2/internal/frontend/desktop/darwin/WailsContext.m +++ b/v2/internal/frontend/desktop/darwin/WailsContext.m @@ -136,7 +136,7 @@ - (BOOL) isFullscreen { return NO; } -- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString*)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight :(bool)fraudulentWebsiteWarningEnabled :(struct Preferences)preferences { +- (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable :(bool)zoomable :(bool)fullscreen :(bool)fullSizeContent :(bool)hideTitleBar :(bool)titlebarAppearsTransparent :(bool)hideTitle :(bool)useToolbar :(bool)hideToolbarSeparator :(bool)webviewIsTransparent :(bool)hideWindowOnClose :(NSString*)appearance :(bool)windowIsTranslucent :(int)minWidth :(int)minHeight :(int)maxWidth :(int)maxHeight :(bool)fraudulentWebsiteWarningEnabled :(struct Preferences)preferences { NSWindowStyleMask styleMask = 0; if( !frameless ) { @@ -158,7 +158,6 @@ - (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable self.mainWindow = [[WailsWindow alloc] initWithContentRect:NSMakeRect(0, 0, width, height) styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]; - if (!frameless && useToolbar) { id toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"]; [toolbar autorelease]; @@ -188,6 +187,10 @@ - (void) CreateWindow:(int)width :(int)height :(bool)frameless :(bool)resizable [self.mainWindow setAppearance:nsAppearance]; } + if (!zoomable && resizable) { + NSButton *button = [self.mainWindow standardWindowButton:NSWindowZoomButton]; + [button setEnabled: NO]; + } NSSize minSize = { minWidth, minHeight }; NSSize maxSize = { maxWidth, maxHeight }; diff --git a/v2/internal/frontend/desktop/darwin/main.m b/v2/internal/frontend/desktop/darwin/main.m index 1dd8bb1f321..75a84dc764f 100644 --- a/v2/internal/frontend/desktop/darwin/main.m +++ b/v2/internal/frontend/desktop/darwin/main.m @@ -203,6 +203,7 @@ int main(int argc, const char * argv[]) { // insert code here... int frameless = 0; int resizable = 1; + int zoomable = 0; int fullscreen = 1; int fullSizeContent = 1; int hideTitleBar = 0; @@ -219,7 +220,7 @@ int main(int argc, const char * argv[]) { int defaultContextMenuEnabled = 1; int windowStartState = 0; int startsHidden = 0; - WailsContext *result = Create("OI OI!",400,400, frameless, resizable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, devtoolsEnabled, defaultContextMenuEnabled, windowStartState, + WailsContext *result = Create("OI OI!",400,400, frameless, resizable, zoomable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, devtoolsEnabled, defaultContextMenuEnabled, windowStartState, startsHidden, 400, 400, 600, 600, false); SetBackgroundColour(result, 255, 0, 0, 255); void *m = NewMenu(""); diff --git a/v2/internal/frontend/desktop/darwin/window.go b/v2/internal/frontend/desktop/darwin/window.go index 236026ee207..458c81eb150 100644 --- a/v2/internal/frontend/desktop/darwin/window.go +++ b/v2/internal/frontend/desktop/darwin/window.go @@ -60,7 +60,7 @@ func NewWindow(frontendOptions *options.App, debug bool, devtools bool) *Window defaultContextMenuEnabled := bool2Cint(debug || frontendOptions.EnableDefaultContextMenu) singleInstanceEnabled := bool2Cint(frontendOptions.SingleInstanceLock != nil) - var fullSizeContent, hideTitleBar, hideTitle, useToolbar, webviewIsTransparent C.int + var fullSizeContent, hideTitleBar, zoomable, hideTitle, useToolbar, webviewIsTransparent C.int var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent C.int var appearance, title *C.char var preferences C.struct_Preferences @@ -108,12 +108,14 @@ func NewWindow(frontendOptions *options.App, debug bool, devtools bool) *Window } } + zoomable = bool2Cint(!frontendOptions.Mac.DisableZoom) + windowIsTranslucent = bool2Cint(mac.WindowIsTranslucent) webviewIsTransparent = bool2Cint(mac.WebviewIsTransparent) appearance = c.String(string(mac.Appearance)) } - var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, fullscreen, fullSizeContent, + var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, zoomable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, devtoolsEnabled, defaultContextMenuEnabled, windowStartState, startsHidden, minWidth, minHeight, maxWidth, maxHeight, enableFraudulentWebsiteWarnings, diff --git a/v2/pkg/options/mac/mac.go b/v2/pkg/options/mac/mac.go index 9d2ccc953c9..85e52755bd1 100644 --- a/v2/pkg/options/mac/mac.go +++ b/v2/pkg/options/mac/mac.go @@ -21,6 +21,7 @@ type Options struct { WebviewIsTransparent bool WindowIsTranslucent bool Preferences *Preferences + DisableZoom bool // ActivationPolicy ActivationPolicy About *AboutInfo OnFileOpen func(filePath string) `json:"-"` diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index 62a6efe07ae..4166f46e1f0 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Added docs to help fix NixOs/Wayland font-size css issue. Added by @atterpac in [PR](https://github.com/wailsapp/wails/pull/3268) - Added -m (skip `go mod tidy`) flag to dev command by @te5se in [PR](https://github.com/wailsapp/wails/pull/3275) +- Added mac option `DisableZoom` to remove zoom button. Added by @wizzymore in [PR](https://github.com/wailsapp/wails/pull/3289) ## v2.8.0 - 2024-02-08 diff --git a/website/versioned_docs/version-v2.8.0/reference/options.mdx b/website/versioned_docs/version-v2.8.0/reference/options.mdx index 26fb1afac27..619b8eaf276 100644 --- a/website/versioned_docs/version-v2.8.0/reference/options.mdx +++ b/website/versioned_docs/version-v2.8.0/reference/options.mdx @@ -109,6 +109,7 @@ func main() { Appearance: mac.NSAppearanceNameDarkAqua, WebviewIsTransparent: true, WindowIsTranslucent: false, + DisableZoom: false, About: &mac.AboutInfo{ Title: "My Application", Message: "© 2021 Me", @@ -897,6 +898,13 @@ Mac: &mac.Options{ } ``` +#### DisableZoom + +By default, the window is zoomable. Setting this to `true` will disable the zoom button (green button). + +Name: DisableZoom
+Type: `bool` + #### About This configuration lets you set the title, message and icon for the "About" menu item in the app menu created by the "AppMenu" role. From 0c3025d695c3f19b39bbb0e42d0f6c72c9eaee59 Mon Sep 17 00:00:00 2001 From: Fabio Massaioli Date: Sat, 2 Mar 2024 06:04:02 +0100 Subject: [PATCH 045/369] [v3] Fix ordering of if branches in WebviewWindow.Restore method (#3279) * Add JS Window API example * Fix ordering of if branches in Window.Restore method * Add changelog entry --- mkdocs-website/docs/en/changelog.md | 1 + v3/pkg/application/webview_window.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mkdocs-website/docs/en/changelog.md b/mkdocs-website/docs/en/changelog.md index 5cc3cb3898f..b77a6bdc787 100644 --- a/mkdocs-website/docs/en/changelog.md +++ b/mkdocs-website/docs/en/changelog.md @@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix MacOS systray click handling when no attached window by [thomas-senechal](https://github.com/thomas-senechal) in PR [#3207](https://github.com/wailsapp/wails/pull/3207) - Fix failing Windows build due to unknown option by [thomas-senechal](https://github.com/thomas-senechal) in PR [#3208](https://github.com/wailsapp/wails/pull/3208) - Fix wrong baseURL when open window twice by @5aaee9 in PR [#3273](https://github.com/wailsapp/wails/pull/3273) +- Fix ordering of if branches in `WebviewWindow.Restore` method by [@fbbdev](https://github.com/fbbdev) in [#3279](https://github.com/wailsapp/wails/pull/3279) ### Changed diff --git a/v3/pkg/application/webview_window.go b/v3/pkg/application/webview_window.go index 84b57d1659d..833ba7a91d8 100644 --- a/v3/pkg/application/webview_window.go +++ b/v3/pkg/application/webview_window.go @@ -962,10 +962,10 @@ func (w *WebviewWindow) Restore() { InvokeSync(func() { if w.IsMinimised() { w.UnMinimise() - } else if w.IsMaximised() { - w.UnMaximise() } else if w.IsFullscreen() { w.UnFullscreen() + } else if w.IsMaximised() { + w.UnMaximise() } w.emit(events.Common.WindowRestore) }) From 964abcc6bd1edffd5a9ed447d7a5806492178aee Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 2 Mar 2024 16:42:20 +1100 Subject: [PATCH 046/369] Escape bindings, even though we generate them internally. --- v2/pkg/assetserver/assetserver.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/v2/pkg/assetserver/assetserver.go b/v2/pkg/assetserver/assetserver.go index 54fe5d0636f..59665c09165 100644 --- a/v2/pkg/assetserver/assetserver.go +++ b/v2/pkg/assetserver/assetserver.go @@ -8,6 +8,7 @@ import ( "strings" "golang.org/x/net/html" + "html/template" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/assetserver" @@ -67,9 +68,11 @@ func NewAssetServer(bindingsJSON string, options assetserver.Options, servingFro } func NewAssetServerWithHandler(handler http.Handler, bindingsJSON string, servingFromDisk bool, logger Logger, runtime RuntimeAssets) (*AssetServer, error) { + var buffer bytes.Buffer if bindingsJSON != "" { - buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n") + escapedBindingsJSON := template.JSEscapeString(bindingsJSON) + buffer.WriteString(`window.wailsbindings='` + escapedBindingsJSON + `';` + "\n") } buffer.Write(runtime.RuntimeDesktopJS()) From 7e687750b2f7df92cfc5f40d5ff9cb8c7674f5d6 Mon Sep 17 00:00:00 2001 From: Fabio Massaioli Date: Sat, 2 Mar 2024 10:10:25 +0100 Subject: [PATCH 047/369] [v3] Add option for showing the toolbar in fullscreen mode on macOS (#3282) * Add option for showing the toolbar in fullscreen mode on macOS * Add an example demonstrating the ShowToolbarWhenFullscreen option * Update docs * Add changelog entry * Run go mod tidy --- mkdocs-website/docs/en/API/fullapi.md | 2 + mkdocs-website/docs/en/changelog.md | 1 + v3/examples/show-macos-toolbar/README.md | 20 ++++++++ v3/examples/show-macos-toolbar/main.go | 51 +++++++++++++++++++++ v3/go.mod | 2 +- v3/pkg/application/options_mac.go | 8 +++- v3/pkg/application/webview_window_darwin.go | 40 +++++++++------- v3/pkg/application/webview_window_darwin.h | 1 + v3/pkg/application/webview_window_darwin.m | 7 +++ 9 files changed, 113 insertions(+), 19 deletions(-) create mode 100644 v3/examples/show-macos-toolbar/README.md create mode 100644 v3/examples/show-macos-toolbar/main.go diff --git a/mkdocs-website/docs/en/API/fullapi.md b/mkdocs-website/docs/en/API/fullapi.md index c6b505e9dd8..91663c6dc5e 100644 --- a/mkdocs-website/docs/en/API/fullapi.md +++ b/mkdocs-website/docs/en/API/fullapi.md @@ -1760,6 +1760,8 @@ type MacTitleBar struct { UseToolbar bool // HideToolbarSeparator will hide the toolbar separator HideToolbarSeparator bool + // ShowToolbarWhenFullscreen will keep the toolbar visible when the window is in fullscreen mode + ShowToolbarWhenFullscreen bool // ToolbarStyle is the style of toolbar to use ToolbarStyle MacToolbarStyle } diff --git a/mkdocs-website/docs/en/changelog.md b/mkdocs-website/docs/en/changelog.md index b77a6bdc787..fa3a3f83826 100644 --- a/mkdocs-website/docs/en/changelog.md +++ b/mkdocs-website/docs/en/changelog.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [darwin] add Event ApplicationShouldHandleReopen to be able to handle dock icon click by @5aaee9 in [#2991](https://github.com/wailsapp/wails/pull/2991) - [darwin] add getPrimaryScreen/getScreens to impl by @tmclane in [#2618](https://github.com/wailsapp/wails/pull/2618) +- [darwin] add option for showing the toolbar in fullscreen mode on macOS by [@fbbdev](https://github.com/fbbdev) in [#3282](https://github.com/wailsapp/wails/pull/3282) - [linux] add onKeyPress logic to convert linux keypress into an accelerator @[Atterpac](https://github.com/Atterpac) in[#3022](https://github.com/wailsapp/wails/pull/3022]) - [linux] add task `run:linux` by [@marcus-crane](https://github.com/marcus-crane) in [#3146](https://github.com/wailsapp/wails/pull/3146) - export `SetIcon` method by @almas1992 in [PR](https://github.com/wailsapp/wails/pull/3147) diff --git a/v3/examples/show-macos-toolbar/README.md b/v3/examples/show-macos-toolbar/README.md new file mode 100644 index 00000000000..21bbeac9656 --- /dev/null +++ b/v3/examples/show-macos-toolbar/README.md @@ -0,0 +1,20 @@ +# Show macOS Toolbar Example + +This example is a demonstration of the macOS option `ShowToolbarWhenFullscreen`, which keeps +the system toolbar visible when in fullscreen mode. + +## Running the example + +To run the example (on macOS), simply run the following command: + +```bash +go run . +``` + +# Status + +| Platform | Status | +|----------|---------| +| Mac | Working | +| Windows | N/A | +| Linux | N/A | diff --git a/v3/examples/show-macos-toolbar/main.go b/v3/examples/show-macos-toolbar/main.go new file mode 100644 index 00000000000..7c7be78aedd --- /dev/null +++ b/v3/examples/show-macos-toolbar/main.go @@ -0,0 +1,51 @@ +package main + +import ( + _ "embed" + "log" + + "github.com/wailsapp/wails/v3/pkg/application" +) + +func main() { + app := application.New(application.Options{ + Name: "Show macOS Toolbar", + Description: "A demo of the ShowToolbarWhenFullscreen option", + Mac: application.MacOptions{ + ApplicationShouldTerminateAfterLastWindowClosed: true, + }, + }) + + // Create window + app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + Title: "Toolbar hidden (default behaviour)", + HTML: "

Switch this window to fullscreen: the toolbar will be hidden

", + CSS: `body { background-color: blue; color: white; height: 100vh; display: flex; justify-content: center; align-items: center; }`, + Mac: application.MacWindow{ + TitleBar: application.MacTitleBar{ + UseToolbar: true, + HideToolbarSeparator: true, + }, + }, + }) + + // Create window + app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + Title: "Toolbar visible", + HTML: "

Switch this window to fullscreen: the toolbar will stay visible

", + CSS: `body { background-color: red; color: white; height: 100vh; display: flex; justify-content: center; align-items: center; }`, + Mac: application.MacWindow{ + TitleBar: application.MacTitleBar{ + UseToolbar: true, + HideToolbarSeparator: true, + ShowToolbarWhenFullscreen: true, + }, + }, + }) + + err := app.Run() + + if err != nil { + log.Fatal(err) + } +} diff --git a/v3/go.mod b/v3/go.mod index 2d0c5008c85..51f502bea2f 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -32,7 +32,6 @@ require ( github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 github.com/pkg/errors v0.9.1 github.com/pterm/pterm v0.12.51 - github.com/rjeczalik/notify v0.9.3 github.com/samber/lo v1.38.1 github.com/tc-hib/winres v0.1.6 github.com/wailsapp/go-webview2 v1.0.9 @@ -84,6 +83,7 @@ require ( github.com/radovskyb/watcher v1.0.7 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.4.4 // indirect + github.com/rjeczalik/notify v0.9.3 // indirect github.com/sajari/fuzzy v1.0.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/skeema/knownhosts v1.2.1 // indirect diff --git a/v3/pkg/application/options_mac.go b/v3/pkg/application/options_mac.go index 1078a5aa33c..6255cc5cec1 100644 --- a/v3/pkg/application/options_mac.go +++ b/v3/pkg/application/options_mac.go @@ -1,7 +1,9 @@ package application -import "github.com/wailsapp/wails/v3/pkg/events" -import "github.com/leaanthony/u" +import ( + "github.com/leaanthony/u" + "github.com/wailsapp/wails/v3/pkg/events" +) // MacBackdrop is the backdrop type for macOS type MacBackdrop int @@ -87,6 +89,8 @@ type MacTitleBar struct { UseToolbar bool // HideToolbarSeparator will hide the toolbar separator HideToolbarSeparator bool + // ShowToolbarWhenFullscreen will keep the toolbar visible when the window is in fullscreen mode + ShowToolbarWhenFullscreen bool // ToolbarStyle is the style of toolbar to use ToolbarStyle MacToolbarStyle } diff --git a/v3/pkg/application/webview_window_darwin.go b/v3/pkg/application/webview_window_darwin.go index 10c0f0ed94f..156dba789f6 100644 --- a/v3/pkg/application/webview_window_darwin.go +++ b/v3/pkg/application/webview_window_darwin.go @@ -443,18 +443,12 @@ void windowSetHideTitle(void* nsWindow, bool hideTitle) { } // Set Window use toolbar -void windowSetUseToolbar(void* nsWindow, bool useToolbar, int toolbarStyle) { +void windowSetUseToolbar(void* nsWindow, bool useToolbar) { WebviewWindow* window = (WebviewWindow*)nsWindow; if( useToolbar ) { NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"wails.toolbar"]; [toolbar autorelease]; [window setToolbar:toolbar]; - - // If macos 11 or higher, set toolbar style - if (@available(macOS 11.0, *)) { - [window setToolbarStyle:toolbarStyle]; - } - } else { [window setToolbar:nil]; } @@ -462,11 +456,15 @@ void windowSetUseToolbar(void* nsWindow, bool useToolbar, int toolbarStyle) { // Set window toolbar style void windowSetToolbarStyle(void* nsWindow, int style) { + WebviewWindow* window = (WebviewWindow*)nsWindow; // use @available to check if the function is available // if not, return if (@available(macOS 11.0, *)) { - NSToolbar* toolbar = [(WebviewWindow*)nsWindow toolbar]; - [toolbar setShowsBaselineSeparator:style]; + NSToolbar* toolbar = [window toolbar]; + if ( toolbar == nil ) { + return; + } + [window setToolbarStyle:style]; } } @@ -479,6 +477,15 @@ void windowSetHideToolbarSeparator(void* nsWindow, bool hideSeparator) { [toolbar setShowsBaselineSeparator:!hideSeparator]; } +// Configure the toolbar auto-hide feature +void windowSetShowToolbarWhenFullscreen(void* window, bool setting) { + WebviewWindow* nsWindow = (WebviewWindow*)window; + // Get delegate + WebviewWindowDelegate* delegate = (WebviewWindowDelegate*)[nsWindow delegate]; + // Set height + delegate.showToolbarWhenFullscreen = setting; +} + // Set Window appearance type void windowSetAppearanceTypeByName(void* nsWindow, const char *appearanceName) { // set window appearance type by name @@ -745,11 +752,12 @@ void windowFocus(void *window) { */ import "C" import ( - "github.com/wailsapp/wails/v3/internal/assetserver" - "github.com/wailsapp/wails/v3/internal/runtime" "sync" "unsafe" + "github.com/wailsapp/wails/v3/internal/assetserver" + "github.com/wailsapp/wails/v3/internal/runtime" + "github.com/wailsapp/wails/v3/pkg/events" ) @@ -968,7 +976,6 @@ func (w *macosWebviewWindow) setEnabled(enabled bool) { } func (w *macosWebviewWindow) execJS(js string) { - InvokeAsync(func() { if globalApplication.performingShutdown { return @@ -1146,11 +1153,12 @@ func (w *macosWebviewWindow) run() { C.windowSetHideTitleBar(w.nsWindow, C.bool(titleBarOptions.Hide)) C.windowSetHideTitle(w.nsWindow, C.bool(titleBarOptions.HideTitle)) C.windowSetFullSizeContent(w.nsWindow, C.bool(titleBarOptions.FullSizeContent)) - if titleBarOptions.UseToolbar { - C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar), C.int(titleBarOptions.ToolbarStyle)) - } + C.windowSetUseToolbar(w.nsWindow, C.bool(titleBarOptions.UseToolbar)) + C.windowSetToolbarStyle(w.nsWindow, C.int(titleBarOptions.ToolbarStyle)) + C.windowSetShowToolbarWhenFullscreen(w.nsWindow, C.bool(titleBarOptions.ShowToolbarWhenFullscreen)) C.windowSetHideToolbarSeparator(w.nsWindow, C.bool(titleBarOptions.HideToolbarSeparator)) } + if macOptions.Appearance != "" { C.windowSetAppearanceTypeByName(w.nsWindow, C.CString(string(macOptions.Appearance))) } @@ -1186,7 +1194,7 @@ func (w *macosWebviewWindow) run() { if options.CSS != "" { C.windowInjectCSS(w.nsWindow, C.CString(options.CSS)) } - if options.Hidden == false { + if !options.Hidden { C.windowShow(w.nsWindow) w.setHasShadow(!options.Mac.DisableShadow) } else { diff --git a/v3/pkg/application/webview_window_darwin.h b/v3/pkg/application/webview_window_darwin.h index aa67e1c3bcc..1dfab739594 100644 --- a/v3/pkg/application/webview_window_darwin.h +++ b/v3/pkg/application/webview_window_darwin.h @@ -23,6 +23,7 @@ @property unsigned int windowId; @property (retain) NSEvent* leftMouseEvent; @property unsigned int invisibleTitleBarHeight; +@property BOOL showToolbarWhenFullscreen; @property NSWindowStyleMask previousStyleMask; // Used to restore the window style mask when using frameless - (void)handleLeftMouseUp:(NSWindow *)window; diff --git a/v3/pkg/application/webview_window_darwin.m b/v3/pkg/application/webview_window_darwin.m index b2ee37e09ec..00f1eeb0be2 100644 --- a/v3/pkg/application/webview_window_darwin.m +++ b/v3/pkg/application/webview_window_darwin.m @@ -241,6 +241,13 @@ - (void)webView:(nonnull WKWebView *)webView stopURLSchemeTask:(nonnull id Date: Mon, 4 Mar 2024 07:50:08 +0100 Subject: [PATCH 048/369] [runtime] Add cancelation of bound method calls and context passing --- .../binding/{ => assets}/bindings_main.js | 4 +- v3/examples/binding/assets/index.html | 1 + v3/examples/binding/assets/runtime.js | 1 + v3/examples/binding/go.mod | 37 ++-- v3/examples/binding/go.sum | 177 ++++++++++-------- v3/examples/frameless/assets/runtime.js | 2 +- v3/examples/window-api/assets/runtime.js | 2 +- v3/examples/wml/assets/runtime.js | 2 +- .../assetserver/assetserver_webview.go | 6 +- .../build_assets/runtime/runtime.debug.js | 29 ++- .../commands/build_assets/runtime/runtime.js | 2 +- v3/internal/parser/bindings.go | 12 +- v3/internal/parser/parser.go | 13 +- .../frontend/bindings/main/GreetService.js | 10 + .../bindings/main/GreetService.name.js | 10 + .../bindings/main/GreetService.name.ts | 5 + .../frontend/bindings/main/GreetService.ts | 5 + .../parser/testdata/function_single/main.go | 9 +- v3/internal/runtime/Taskfile.yaml | 1 + .../desktop/@wailsio/runtime/src/calls.js | 33 +++- .../desktop/@wailsio/runtime/src/runtime.js | 1 + v3/pkg/application/assets/alpha/runtime.js | 2 +- v3/pkg/application/bindings.go | 14 +- v3/pkg/application/messageprocessor.go | 11 +- v3/pkg/application/messageprocessor_call.go | 54 +++++- 25 files changed, 319 insertions(+), 124 deletions(-) rename v3/examples/binding/{ => assets}/bindings_main.js (66%) create mode 100644 v3/examples/binding/assets/runtime.js diff --git a/v3/examples/binding/bindings_main.js b/v3/examples/binding/assets/bindings_main.js similarity index 66% rename from v3/examples/binding/bindings_main.js rename to v3/examples/binding/assets/bindings_main.js index d7dab3886d5..5636aa15466 100644 --- a/v3/examples/binding/bindings_main.js +++ b/v3/examples/binding/assets/bindings_main.js @@ -13,7 +13,7 @@ window.go.main = { * @param name {string} * @returns {Promise} **/ - Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); }, + Greet: function(name) { return wails.Call.ByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); }, /** * GreetService.GreetPerson @@ -21,6 +21,6 @@ window.go.main = { * @param person {main.Person} * @returns {Promise} **/ - GreetPerson: function(person) { return wails.CallByID(4021313248, ...Array.prototype.slice.call(arguments, 0)); }, + GreetPerson: function(person) { return wails.Call.ByID(4021313248, ...Array.prototype.slice.call(arguments, 0)); }, }, }; diff --git a/v3/examples/binding/assets/index.html b/v3/examples/binding/assets/index.html index e437080e432..7f841393b11 100644 --- a/v3/examples/binding/assets/index.html +++ b/v3/examples/binding/assets/index.html @@ -80,6 +80,7 @@ + diff --git a/v3/examples/window/main.go b/v3/examples/window/main.go index 9c0e390f35d..41fc4660b96 100644 --- a/v3/examples/window/main.go +++ b/v3/examples/window/main.go @@ -24,7 +24,7 @@ func main() { ApplicationShouldTerminateAfterLastWindowClosed: false, }, }) - app.On(events.Mac.ApplicationDidFinishLaunching, func(event *application.Event) { + app.On(events.Common.ApplicationStarted, func(event *application.Event) { log.Println("ApplicationDidFinishLaunching") }) diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index 4272cd5c312..c3b54673d4e 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -35,7 +35,7 @@ type linuxApp struct { theme string } -func (m *linuxApp) GetFlags(options Options) map[string]any { +func (l *linuxApp) GetFlags(options Options) map[string]any { if options.Flags == nil { options.Flags = make(map[string]any) } @@ -46,30 +46,30 @@ func getNativeApplication() *linuxApp { return globalApplication.impl.(*linuxApp) } -func (m *linuxApp) hide() { - hideAllWindows(m.application) +func (l *linuxApp) hide() { + hideAllWindows(l.application) } -func (m *linuxApp) show() { - showAllWindows(m.application) +func (l *linuxApp) show() { + showAllWindows(l.application) } -func (m *linuxApp) on(eventID uint) { +func (l *linuxApp) on(eventID uint) { // TODO: What do we need to do here? log.Println("linuxApp.on()", eventID) } -func (m *linuxApp) setIcon(icon []byte) { +func (l *linuxApp) setIcon(icon []byte) { log.Println("linuxApp.setIcon", "not implemented") } -func (m *linuxApp) name() string { +func (l *linuxApp) name() string { return appName() } -func (m *linuxApp) getCurrentWindowID() uint { - return getCurrentWindowID(m.application, m.windows) +func (l *linuxApp) getCurrentWindowID() uint { + return getCurrentWindowID(l.application, l.windows) } type rnr struct { @@ -80,9 +80,9 @@ func (r rnr) run() { r.f() } -func (m *linuxApp) getApplicationMenu() pointer { - if m.applicationMenu != nilPointer { - return m.applicationMenu +func (l *linuxApp) getApplicationMenu() pointer { + if l.applicationMenu != nilPointer { + return l.applicationMenu } menu := globalApplication.ApplicationMenu @@ -90,12 +90,12 @@ func (m *linuxApp) getApplicationMenu() pointer { InvokeSync(func() { menu.Update() }) - m.applicationMenu = (menu.impl).(*linuxMenu).native + l.applicationMenu = (menu.impl).(*linuxMenu).native } - return m.applicationMenu + return l.applicationMenu } -func (m *linuxApp) setApplicationMenu(menu *Menu) { +func (l *linuxApp) setApplicationMenu(menu *Menu) { // FIXME: How do we avoid putting a menu? if menu == nil { // Create a default menu @@ -104,46 +104,44 @@ func (m *linuxApp) setApplicationMenu(menu *Menu) { } } -func (m *linuxApp) run() error { +func (l *linuxApp) run() error { - // Add a hook to the ApplicationDidFinishLaunching event - // FIXME: add Wails specific events - i.e. Shouldn't platform specific ones be translated to Wails events? - m.parent.On(events.Mac.ApplicationDidFinishLaunching, func(evt *Event) { - // Do we need to do anything now? - fmt.Println("events.Mac.ApplicationDidFinishLaunching received!") + l.parent.On(events.Linux.ApplicationStartup, func(evt *Event) { + fmt.Println("events.Linux.ApplicationStartup received!") }) - m.monitorThemeChanges() - return appRun(m.application) + l.setupCommonEvents() + l.monitorThemeChanges() + return appRun(l.application) } -func (m *linuxApp) destroy() { +func (l *linuxApp) destroy() { if !globalApplication.shouldQuit() { return } globalApplication.cleanup() - appDestroy(m.application) + appDestroy(l.application) } -func (m *linuxApp) isOnMainThread() bool { +func (l *linuxApp) isOnMainThread() bool { return isOnMainThread() } // register our window to our parent mapping -func (m *linuxApp) registerWindow(window pointer, id uint) { - m.windowsLock.Lock() - m.windows[windowPointer(window)] = id - m.windowsLock.Unlock() +func (l *linuxApp) registerWindow(window pointer, id uint) { + l.windowsLock.Lock() + l.windows[windowPointer(window)] = id + l.windowsLock.Unlock() } -func (m *linuxApp) isDarkMode() bool { - return strings.Contains(m.theme, "dark") +func (l *linuxApp) isDarkMode() bool { + return strings.Contains(l.theme, "dark") } -func (m *linuxApp) monitorThemeChanges() { +func (l *linuxApp) monitorThemeChanges() { go func() { conn, err := dbus.ConnectSessionBus() if err != nil { - m.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err) + l.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err) return } defer conn.Close() @@ -176,10 +174,10 @@ func (m *linuxApp) monitorThemeChanges() { continue } - if theme != m.theme { - m.theme = theme + if theme != l.theme { + l.theme = theme event := newApplicationEvent(events.Common.ThemeChanged) - event.Context().setIsDarkMode(m.isDarkMode()) + event.Context().setIsDarkMode(l.isDarkMode()) applicationEvents <- event } diff --git a/v3/pkg/application/dialogs_linux.go b/v3/pkg/application/dialogs_linux.go index 4943766f0af..49499dda14e 100644 --- a/v3/pkg/application/dialogs_linux.go +++ b/v3/pkg/application/dialogs_linux.go @@ -1,7 +1,7 @@ package application -func (m *linuxApp) showAboutDialog(title string, message string, icon []byte) { - window := globalApplication.getWindowForID(m.getCurrentWindowID()) +func (l *linuxApp) showAboutDialog(title string, message string, icon []byte) { + window := globalApplication.getWindowForID(l.getCurrentWindowID()) var parent uintptr if window != nil { parent, _ = window.(*WebviewWindow).NativeWindowHandle() diff --git a/v3/pkg/application/events_common_linux.go b/v3/pkg/application/events_common_linux.go new file mode 100644 index 00000000000..530ac1563ab --- /dev/null +++ b/v3/pkg/application/events_common_linux.go @@ -0,0 +1,21 @@ +//go:build linux + +package application + +import "github.com/wailsapp/wails/v3/pkg/events" + +var commonApplicationEventMap = map[events.ApplicationEventType]events.ApplicationEventType{ + events.Linux.ApplicationStartup: events.Common.ApplicationStarted, + events.Linux.SystemThemeChanged: events.Common.ThemeChanged, +} + +func (l *linuxApp) setupCommonEvents() { + for sourceEvent, targetEvent := range commonApplicationEventMap { + sourceEvent := sourceEvent + targetEvent := targetEvent + l.parent.On(sourceEvent, func(event *Event) { + event.Id = uint(targetEvent) + applicationEvents <- event + }) + } +} diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 36db3d50658..379af2547e8 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -206,7 +206,36 @@ func dispatchOnMainThreadCallback(callbackID C.uint) { //export activateLinux func activateLinux(data pointer) { - // NOOP: Callback for now + processApplicationEvent(C.uint(events.Linux.ApplicationStartup), data) +} + +//export processApplicationEvent +func processApplicationEvent(eventID C.uint, data pointer) { + event := newApplicationEvent(events.ApplicationEventType(eventID)) + + //if data != nil { + // dataCStrJSON := C.serializationNSDictionary(data) + // if dataCStrJSON != nil { + // defer C.free(unsafe.Pointer(dataCStrJSON)) + // + // dataJSON := C.GoString(dataCStrJSON) + // var result map[string]any + // err := json.Unmarshal([]byte(dataJSON), &result) + // + // if err != nil { + // panic(err) + // } + // + // event.Context().setData(result) + // } + //} + + switch event.Id { + case uint(events.Linux.SystemThemeChanged): + isDark := globalApplication.IsDarkMode() + event.Context().setIsDarkMode(isDark) + } + applicationEvents <- event } func isOnMainThread() bool { @@ -236,17 +265,12 @@ func appNew(name string) pointer { func appRun(app pointer) error { application := (*C.GApplication)(app) + //TODO: Only set this if we configure it to do so C.g_application_hold(application) // allows it to run without a window signal := C.CString("activate") defer C.free(unsafe.Pointer(signal)) - C.g_signal_connect_data( - C.gpointer(application), - signal, - C.GCallback(C.activateLinux), - nil, - nil, - 0) + C.signal_connect(unsafe.Pointer(application), signal, C.activateLinux, nil) status := C.g_application_run(application, 0, nil) C.g_application_release(application) C.g_object_unref(C.gpointer(app)) diff --git a/v3/pkg/application/mainthread_linux.go b/v3/pkg/application/mainthread_linux.go index 572b081be3e..2a5ff3e2cb3 100644 --- a/v3/pkg/application/mainthread_linux.go +++ b/v3/pkg/application/mainthread_linux.go @@ -2,7 +2,7 @@ package application -func (m *linuxApp) dispatchOnMainThread(id uint) { +func (l *linuxApp) dispatchOnMainThread(id uint) { dispatchOnMainThread(id) } diff --git a/v3/pkg/application/screen_linux.go b/v3/pkg/application/screen_linux.go index 36411045486..526752aceba 100644 --- a/v3/pkg/application/screen_linux.go +++ b/v3/pkg/application/screen_linux.go @@ -7,17 +7,17 @@ import ( "sync" ) -func (m *linuxApp) getPrimaryScreen() (*Screen, error) { +func (l *linuxApp) getPrimaryScreen() (*Screen, error) { return nil, fmt.Errorf("not implemented") } -func (m *linuxApp) getScreens() ([]*Screen, error) { +func (l *linuxApp) getScreens() ([]*Screen, error) { var wg sync.WaitGroup var screens []*Screen var err error wg.Add(1) InvokeSync(func() { - screens, err = getScreens(m.application) + screens, err = getScreens(l.application) wg.Done() }) wg.Wait() diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 1f36059ee86..5314ea6bbed 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -259,11 +259,12 @@ func (w *linuxWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) { func newWindowImpl(parent *WebviewWindow) *linuxWebviewWindow { // (*C.struct__GtkWidget)(m.native) //var menubar *C.struct__GtkWidget - return &linuxWebviewWindow{ + result := &linuxWebviewWindow{ application: getNativeApplication().application, parent: parent, // menubar: menubar, } + return result } func (w *linuxWebviewWindow) setTitle(title string) { @@ -405,9 +406,7 @@ func (w *linuxWebviewWindow) run() { } w.setURL(startURL) - // We need to wait for the HTML to load before we can execute the javascript - // FIXME: What event is this? DomReady? - w.parent.On(events.Mac.WebViewDidFinishNavigation, func(_ *WindowEvent) { + w.parent.On(events.Linux.WindowLoadChanged, func(_ *WindowEvent) { if w.parent.options.JS != "" { w.execJS(w.parent.options.JS) } @@ -416,6 +415,9 @@ func (w *linuxWebviewWindow) run() { w.execJS(js) } }) + w.parent.On(events.Linux.WindowDeleteEvent, func(e *WindowEvent) { + w.parent.emit(events.Common.WindowClosing) + }) w.parent.RegisterHook(events.Linux.WindowLoadChanged, func(e *WindowEvent) { w.execJS(runtime.Core()) }) From 4c7b6432950ebd1595d22ab0ea93db47c11e881d Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 5 Feb 2024 21:37:35 +1100 Subject: [PATCH 053/369] Add webview GPU policy and update Linux options The commit introduces a set of webview GPU policies to control hardware acceleration. These policies define when hardware acceleration is enabled on the webview. An option for this has been added to the LinuxWindow struct for Linux specific windows. Additional code modification was carried out to use this new GPU policy option when calling `windowNew` function. Finally, the sequence of the GPU Policies in the const declaration has been updated for better readability. --- v2/pkg/options/linux/linux.go | 6 +-- v3/pkg/application/linux_cgo.go | 32 +++++++-------- v3/pkg/application/options_linux.go | 41 +++++++++++++++++++- v3/pkg/application/options_webview_window.go | 3 ++ v3/pkg/application/webview_window_linux.go | 3 +- 5 files changed, 60 insertions(+), 25 deletions(-) diff --git a/v2/pkg/options/linux/linux.go b/v2/pkg/options/linux/linux.go index 797450c2725..1287f1da2b5 100644 --- a/v2/pkg/options/linux/linux.go +++ b/v2/pkg/options/linux/linux.go @@ -4,10 +4,10 @@ package linux type WebviewGpuPolicy int const ( - // WebviewGpuPolicyAlways Hardware acceleration is always enabled. - WebviewGpuPolicyAlways WebviewGpuPolicy = iota // WebviewGpuPolicyOnDemand Hardware acceleration is enabled/disabled as request by web contents. - WebviewGpuPolicyOnDemand + WebviewGpuPolicyOnDemand WebviewGpuPolicy = iota + // WebviewGpuPolicyAlways Hardware acceleration is always enabled. + WebviewGpuPolicyAlways // WebviewGpuPolicyNever Hardware acceleration is always disabled. WebviewGpuPolicyNever ) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 379af2547e8..73e32247b79 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -793,7 +793,7 @@ func windowMinimize(window pointer) { C.gtk_window_iconify((*C.GtkWindow)(window)) } -func windowNew(application pointer, menu pointer, windowId uint, gpuPolicy int) (window, webview, vbox pointer) { +func windowNew(application pointer, menu pointer, windowId uint, gpuPolicy WebviewGpuPolicy) (window, webview, vbox pointer) { window = pointer(C.gtk_application_window_new((*C.GtkApplication)(application))) C.g_object_ref_sink(C.gpointer(window)) webview = windowNewWebview(windowId, gpuPolicy) @@ -810,45 +810,39 @@ func windowNew(application pointer, menu pointer, windowId uint, gpuPolicy int) return } -func windowNewWebview(parentId uint, gpuPolicy int) pointer { +func windowNewWebview(parentId uint, gpuPolicy WebviewGpuPolicy) pointer { + c := NewCalloc() + defer c.Free() manager := C.webkit_user_content_manager_new() - external := C.CString("external") - C.webkit_user_content_manager_register_script_message_handler(manager, external) - C.free(unsafe.Pointer(external)) - webview := C.webkit_web_view_new_with_user_content_manager(manager) + C.webkit_user_content_manager_register_script_message_handler(manager, c.String("external")) + webView := C.webkit_web_view_new_with_user_content_manager(manager) id := C.uint(parentId) if !registered { - wails := C.CString("wails") C.webkit_web_context_register_uri_scheme( C.webkit_web_context_get_default(), - wails, + c.String("wails"), C.WebKitURISchemeRequestCallback(C.onProcessRequest), C.gpointer(&id), nil) registered = true - C.free(unsafe.Pointer(wails)) } - settings := C.webkit_web_view_get_settings((*C.WebKitWebView)(unsafe.Pointer(webview))) - wails_io := C.CString("wails.io") - empty := C.CString("") - defer C.free(unsafe.Pointer(wails_io)) - defer C.free(unsafe.Pointer(empty)) - C.webkit_settings_set_user_agent_with_application_details(settings, wails_io, empty) + settings := C.webkit_web_view_get_settings((*C.WebKitWebView)(unsafe.Pointer(webView))) + C.webkit_settings_set_user_agent_with_application_details(settings, c.String("wails.io"), c.String("")) switch gpuPolicy { - case 0: + case WebviewGpuPolicyAlways: C.webkit_settings_set_hardware_acceleration_policy(settings, C.WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS) break - case 1: + case WebviewGpuPolicyOnDemand: C.webkit_settings_set_hardware_acceleration_policy(settings, C.WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND) break - case 2: + case WebviewGpuPolicyNever: C.webkit_settings_set_hardware_acceleration_policy(settings, C.WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER) break default: C.webkit_settings_set_hardware_acceleration_policy(settings, C.WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND) } - return pointer(webview) + return pointer(webView) } func windowPresent(window pointer) { diff --git a/v3/pkg/application/options_linux.go b/v3/pkg/application/options_linux.go index bf3d0c308f4..3a471902ce3 100644 --- a/v3/pkg/application/options_linux.go +++ b/v3/pkg/application/options_linux.go @@ -1,6 +1,43 @@ package application -// LinuxWindow contains macOS specific options +// WebviewGpuPolicy values used for determining the webview's hardware acceleration policy. +type WebviewGpuPolicy int + +const ( + // WebviewGpuPolicyAlways Hardware acceleration is always enabled. + WebviewGpuPolicyAlways WebviewGpuPolicy = iota + // WebviewGpuPolicyOnDemand Hardware acceleration is enabled/disabled as request by web contents. + WebviewGpuPolicyOnDemand + // WebviewGpuPolicyNever Hardware acceleration is always disabled. + WebviewGpuPolicyNever +) + +// LinuxWindow specific to Linux windows type LinuxWindow struct { - ShowApplicationMenu bool + // Icon Sets up the icon representing the window. This icon is used when the window is minimized + // (also known as iconified). + Icon []byte + + // WindowIsTranslucent sets the window's background to transparent when enabled. + WindowIsTranslucent bool + + // WebviewGpuPolicy used for determining the hardware acceleration policy for the webview. + // - WebviewGpuPolicyAlways + // - WebviewGpuPolicyOnDemand + // - WebviewGpuPolicyNever + // + // Due to https://github.com/wailsapp/wails/issues/2977, if options.Linux is nil + // in the call to wails.Run(), WebviewGpuPolicy is set by default to WebviewGpuPolicyNever. + // Client code may override this behavior by passing a non-nil Options and set + // WebviewGpuPolicy as needed. + WebviewGpuPolicy WebviewGpuPolicy + + // ProgramName is used to set the program's name for the window manager via GTK's g_set_prgname(). + //This name should not be localized. [see the docs] + // + //When a .desktop file is created this value helps with window grouping and desktop icons when the .desktop file's Name + //property differs form the executable's filename. + // + //[see the docs]: https://docs.gtk.org/glib/func.set_prgname.html + ProgramName string } diff --git a/v3/pkg/application/options_webview_window.go b/v3/pkg/application/options_webview_window.go index d2bccba4573..7164066e7e9 100644 --- a/v3/pkg/application/options_webview_window.go +++ b/v3/pkg/application/options_webview_window.go @@ -100,6 +100,9 @@ type WebviewWindowOptions struct { // Windows options Windows WindowsWindow + // Linux options + Linux LinuxWindow + // ShouldClose is called when the window is about to close. // Return true to allow the window to close, or false to prevent it from closing. ShouldClose func(window *WebviewWindow) bool diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 5314ea6bbed..3df64706df3 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -2,6 +2,7 @@ package application +import "C" import ( "fmt" "github.com/wailsapp/wails/v3/internal/assetserver" @@ -354,7 +355,7 @@ func (w *linuxWebviewWindow) run() { app := getNativeApplication() menu := app.getApplicationMenu() - w.window, w.webview, w.vbox = windowNew(app.application, menu, w.parent.id, 1) + w.window, w.webview, w.vbox = windowNew(app.application, menu, w.parent.id, w.parent.options.Linux.WebviewGpuPolicy) app.registerWindow(w.window, w.parent.id) // record our mapping w.connectSignals() if w.parent.options.EnableDragAndDrop { From 809863d61a0f2c684aab49d58b2c07ddfea87f5a Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 6 Feb 2024 05:50:36 +1100 Subject: [PATCH 054/369] Refactor Linux application handling in webview This update introduces a LinuxOptions struct for Linux-specific application configurations and refines webview for Linux. The 'windows' map has been renamed to 'windowMap' to avoid confusion. Moreover, a method to unregister Windows has been added to ensure the Linux application automatically quits when the last window closes, unless explicitly disabled in the new LinuxOptions structure. Reset Window position after hiding. Some debug output has been removed. --- v3/pkg/application/application_linux.go | 25 +++++++++---- v3/pkg/application/options_application.go | 3 ++ .../application/options_application_linux.go | 7 ++++ v3/pkg/application/webview_window_linux.go | 36 ++++++++++--------- 4 files changed, 47 insertions(+), 24 deletions(-) create mode 100644 v3/pkg/application/options_application_linux.go diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index c3b54673d4e..a72775f0b41 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -29,8 +29,8 @@ type linuxApp struct { startupActions []func() // Native -> uint - windows map[windowPointer]uint - windowsLock sync.Mutex + windowMap map[windowPointer]uint + windowMapLock sync.Mutex theme string } @@ -69,7 +69,7 @@ func (l *linuxApp) name() string { } func (l *linuxApp) getCurrentWindowID() uint { - return getCurrentWindowID(l.application, l.windows) + return getCurrentWindowID(l.application, l.windowMap) } type rnr struct { @@ -114,6 +114,17 @@ func (l *linuxApp) run() error { return appRun(l.application) } +func (l *linuxApp) unregisterWindow(w windowPointer) { + l.windowMapLock.Lock() + delete(l.windowMap, w) + l.windowMapLock.Unlock() + + // If this was the last window... + if len(l.windowMap) == 0 && !l.parent.options.Linux.DisableQuitOnLastWindowClosed { + l.destroy() + } +} + func (l *linuxApp) destroy() { if !globalApplication.shouldQuit() { return @@ -128,9 +139,9 @@ func (l *linuxApp) isOnMainThread() bool { // register our window to our parent mapping func (l *linuxApp) registerWindow(window pointer, id uint) { - l.windowsLock.Lock() - l.windows[windowPointer(window)] = id - l.windowsLock.Unlock() + l.windowMapLock.Lock() + l.windowMap[windowPointer(window)] = id + l.windowMapLock.Unlock() } func (l *linuxApp) isDarkMode() bool { @@ -193,7 +204,7 @@ func newPlatformApp(parent *App) *linuxApp { app := &linuxApp{ parent: parent, application: appNew(name), - windows: map[windowPointer]uint{}, + windowMap: map[windowPointer]uint{}, } return app } diff --git a/v3/pkg/application/options_application.go b/v3/pkg/application/options_application.go index 10bf75188eb..b60dfd85f7e 100644 --- a/v3/pkg/application/options_application.go +++ b/v3/pkg/application/options_application.go @@ -24,6 +24,9 @@ type Options struct { // Windows is the Windows specific configuration for Windows builds Windows WindowsOptions + // Linux is the Linux specific configuration for Linux builds + Linux LinuxOptions + // Bind allows you to bind Go methods to the frontend. Bind []any diff --git a/v3/pkg/application/options_application_linux.go b/v3/pkg/application/options_application_linux.go new file mode 100644 index 00000000000..8c3741ca67d --- /dev/null +++ b/v3/pkg/application/options_application_linux.go @@ -0,0 +1,7 @@ +package application + +// LinuxOptions contains options for Linux applications. +type LinuxOptions struct { + // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. + DisableQuitOnLastWindowClosed bool +} diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 3df64706df3..75055ddf53c 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -21,18 +21,19 @@ type dragInfo struct { } type linuxWebviewWindow struct { - id uint - application pointer - window pointer - webview pointer - parent *WebviewWindow - menubar pointer - vbox pointer - menu *Menu - accels pointer - lastWidth int - lastHeight int - drag dragInfo + id uint + application pointer + window pointer + webview pointer + parent *WebviewWindow + menubar pointer + vbox pointer + menu *Menu + accels pointer + lastWidth int + lastHeight int + drag dragInfo + lastX, lastY int } var ( @@ -109,9 +110,12 @@ func (w *linuxWebviewWindow) focus() { func (w *linuxWebviewWindow) show() { windowShow(w.window) + w.setAbsolutePosition(w.lastX, w.lastY) } func (w *linuxWebviewWindow) hide() { + // save position + w.lastX, w.lastY = windowGetAbsolutePosition(w.window) windowHide(w.window) } @@ -140,7 +144,7 @@ func (w *linuxWebviewWindow) unfullscreen() { func (w *linuxWebviewWindow) fullscreen() { w.maximise() - w.lastWidth, w.lastHeight = w.size() + //w.lastWidth, w.lastHeight = w.size() x, y, width, height, scale := windowGetCurrentMonitorGeometry(w.window) if x == -1 && y == -1 && width == -1 && height == -1 { return @@ -172,9 +176,7 @@ func (w *linuxWebviewWindow) flash(enabled bool) { } func (w *linuxWebviewWindow) on(eventID uint) { - // Don't think this is correct! - // GTK Events are strings - fmt.Println("on()", eventID) + // TODO: Test register/unregister listener for linux events //C.registerListener(C.uint(eventID)) } @@ -188,6 +190,7 @@ func (w *linuxWebviewWindow) windowZoom() { func (w *linuxWebviewWindow) close() { windowClose(w.window) + getNativeApplication().unregisterWindow(windowPointer(w.window)) } func (w *linuxWebviewWindow) zoomIn() { @@ -388,7 +391,6 @@ func (w *linuxWebviewWindow) run() { if w.parent.options.X != 0 || w.parent.options.Y != 0 { w.setRelativePosition(w.parent.options.X, w.parent.options.Y) } else { - fmt.Println("attempting to set in the center") w.center() } switch w.parent.options.StartState { From 3d93c83920e1044ce0ab736df69524ad283bc3bc Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 6 Feb 2024 21:14:51 +1100 Subject: [PATCH 055/369] Added menu cloning. Introduced the ability to clone a menu, along with its submenus, in Linux-based web applications to create a full deep copy. This fixes reusing the application menu for window menus. --- v3/examples/window/main.go | 32 ++++++++++--------- v3/pkg/application/application_linux.go | 24 +++----------- v3/pkg/application/keys.go | 5 +++ v3/pkg/application/linux_cgo.go | 16 +++++++++- v3/pkg/application/menu.go | 11 +++++++ v3/pkg/application/menuitem.go | 26 +++++++++++++++ .../messageprocessor_contextmenu.go | 9 ++++++ v3/pkg/application/options_webview_window.go | 2 +- v3/pkg/application/webview_window_linux.go | 25 +++++++++++++-- 9 files changed, 111 insertions(+), 39 deletions(-) diff --git a/v3/examples/window/main.go b/v3/examples/window/main.go index 41fc4660b96..4a31eaa0a04 100644 --- a/v3/examples/window/main.go +++ b/v3/examples/window/main.go @@ -154,21 +154,23 @@ func main() { }).Show() windowCounter++ }) - myMenu.Add("New WebviewWindow (ignores mouse events"). - SetAccelerator("CmdOrCtrl+F"). - OnClick(func(ctx *application.Context) { - app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ - HTML: "
", - X: rand.Intn(1000), - Y: rand.Intn(800), - IgnoreMouseEvents: true, - BackgroundType: application.BackgroundTypeTransparent, - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - }, - }).Show() - windowCounter++ - }) + if runtime.GOOS != "linux" { + myMenu.Add("New WebviewWindow (ignores mouse events)"). + SetAccelerator("CmdOrCtrl+F"). + OnClick(func(ctx *application.Context) { + app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ + HTML: "
", + X: rand.Intn(1000), + Y: rand.Intn(800), + IgnoreMouseEvents: true, + BackgroundType: application.BackgroundTypeTransparent, + Mac: application.MacWindow{ + InvisibleTitleBarHeight: 50, + }, + }).Show() + windowCounter++ + }) + } if runtime.GOOS == "darwin" { myMenu.Add("New WebviewWindow (MacTitleBarHiddenInset)"). OnClick(func(ctx *application.Context) { diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index a72775f0b41..2d50e988895 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -22,9 +22,8 @@ func init() { } type linuxApp struct { - application pointer - applicationMenu pointer - parent *App + application pointer + parent *App startupActions []func() @@ -55,8 +54,8 @@ func (l *linuxApp) show() { } func (l *linuxApp) on(eventID uint) { - // TODO: What do we need to do here? - log.Println("linuxApp.on()", eventID) + // TODO: Test register/unregister events + //C.registerApplicationEvent(l.application, C.uint(eventID)) } func (l *linuxApp) setIcon(icon []byte) { @@ -80,21 +79,6 @@ func (r rnr) run() { r.f() } -func (l *linuxApp) getApplicationMenu() pointer { - if l.applicationMenu != nilPointer { - return l.applicationMenu - } - - menu := globalApplication.ApplicationMenu - if menu != nil { - InvokeSync(func() { - menu.Update() - }) - l.applicationMenu = (menu.impl).(*linuxMenu).native - } - return l.applicationMenu -} - func (l *linuxApp) setApplicationMenu(menu *Menu) { // FIXME: How do we avoid putting a menu? if menu == nil { diff --git a/v3/pkg/application/keys.go b/v3/pkg/application/keys.go index 4a6fc0e6494..b366c10665e 100644 --- a/v3/pkg/application/keys.go +++ b/v3/pkg/application/keys.go @@ -70,6 +70,11 @@ type accelerator struct { Modifiers []modifier } +func (a *accelerator) clone() *accelerator { + result := *a + return &result +} + func (a *accelerator) String() string { var result []string // Sort modifiers diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 73e32247b79..beba773fe6f 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -13,7 +13,7 @@ import ( ) /* -#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 javascriptcoregtk-4.1 +#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 javascriptcoregtk-4.1 gdk-3.0 #include #include @@ -697,6 +697,10 @@ func windowDestroy(window pointer) { //C.gtk_widget_destroy((*C.GtkWidget)(window)) } +func menuDestroy(gtkMenu pointer) { + C.gtk_widget_destroy((*C.GtkWidget)(gtkMenu)) +} + func windowFullscreen(window pointer) { C.gtk_window_fullscreen((*C.GtkWindow)(window)) } @@ -867,6 +871,16 @@ func windowShow(window pointer) { C.gtk_widget_show_all((*C.GtkWidget)(window)) } +func windowIgnoreMouseEvents(window pointer, webview pointer, ignore bool) { + var enable C.int + if ignore { + enable = 1 + } + gdkWindow := (*C.GdkWindow)(window) + C.gdk_window_set_pass_through(gdkWindow, enable) + C.webkit_web_view_set_editable((*C.WebKitWebView)(webview), C.gboolean(enable)) +} + func windowSetBackgroundColour(vbox, webview pointer, colour RGBA) { rgba := C.GdkRGBA{C.double(colour.Red) / 255.0, C.double(colour.Green) / 255.0, C.double(colour.Blue) / 255.0, C.double(colour.Alpha) / 255.0} C.webkit_web_view_set_background_color((*C.WebKitWebView)(webview), &rgba) diff --git a/v3/pkg/application/menu.go b/v3/pkg/application/menu.go index f4a18f39a08..25a844a4509 100644 --- a/v3/pkg/application/menu.go +++ b/v3/pkg/application/menu.go @@ -95,6 +95,17 @@ func (m *Menu) setContextData(data *ContextMenuData) { } } +// Clone recursively clones the menu and all its submenus. +func (m *Menu) clone() *Menu { + result := &Menu{ + label: m.label, + } + for _, item := range m.items { + result.items = append(result.items, item.clone()) + } + return result +} + func (a *App) NewMenu() *Menu { return &Menu{} } diff --git a/v3/pkg/application/menuitem.go b/v3/pkg/application/menuitem.go index f363fb7409e..7e0910a4df9 100644 --- a/v3/pkg/application/menuitem.go +++ b/v3/pkg/application/menuitem.go @@ -332,3 +332,29 @@ func (m *MenuItem) setContextData(data *ContextMenuData) { m.submenu.setContextData(data) } } + +// clone returns a deep copy of the MenuItem +func (m *MenuItem) clone() *MenuItem { + result := &MenuItem{ + id: m.id, + label: m.label, + tooltip: m.tooltip, + disabled: m.disabled, + checked: m.checked, + hidden: m.hidden, + bitmap: m.bitmap, + callback: m.callback, + itemType: m.itemType, + role: m.role, + } + if m.submenu != nil { + result.submenu = m.submenu.clone() + } + if m.accelerator != nil { + result.accelerator = m.accelerator.clone() + } + if m.contextMenuData != nil { + result.contextMenuData = m.contextMenuData.clone() + } + return result +} diff --git a/v3/pkg/application/messageprocessor_contextmenu.go b/v3/pkg/application/messageprocessor_contextmenu.go index c7c8a86a892..0d7f2e8948b 100644 --- a/v3/pkg/application/messageprocessor_contextmenu.go +++ b/v3/pkg/application/messageprocessor_contextmenu.go @@ -11,6 +11,15 @@ type ContextMenuData struct { Data any `json:"data"` } +func (d ContextMenuData) clone() *ContextMenuData { + return &ContextMenuData{ + Id: d.Id, + X: d.X, + Y: d.Y, + Data: d.Data, + } +} + const ( ContextMenuOpen = 0 ) diff --git a/v3/pkg/application/options_webview_window.go b/v3/pkg/application/options_webview_window.go index 7164066e7e9..c20585076ff 100644 --- a/v3/pkg/application/options_webview_window.go +++ b/v3/pkg/application/options_webview_window.go @@ -116,7 +116,7 @@ type WebviewWindowOptions struct { // KeyBindings is a map of key bindings to functions KeyBindings map[string]func(window *WebviewWindow) - // IgnoreMouseEvents will ignore mouse events in the window + // IgnoreMouseEvents will ignore mouse events in the window (Windows + Mac only) IgnoreMouseEvents bool } diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 75055ddf53c..80d5b9831bb 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -34,6 +34,7 @@ type linuxWebviewWindow struct { lastHeight int drag dragInfo lastX, lastY int + gtkmenu pointer } var ( @@ -357,8 +358,19 @@ func (w *linuxWebviewWindow) run() { app := getNativeApplication() - menu := app.getApplicationMenu() - w.window, w.webview, w.vbox = windowNew(app.application, menu, w.parent.id, w.parent.options.Linux.WebviewGpuPolicy) + var menu = w.menu + if menu == nil && globalApplication.ApplicationMenu != nil { + menu = globalApplication.ApplicationMenu.clone() + } + if menu != nil { + InvokeSync(func() { + menu.Update() + }) + w.menu = menu + w.gtkmenu = (menu.impl).(*linuxMenu).native + } + + w.window, w.webview, w.vbox = windowNew(app.application, w.gtkmenu, w.parent.id, w.parent.options.Linux.WebviewGpuPolicy) app.registerWindow(w.window, w.parent.id) // record our mapping w.connectSignals() if w.parent.options.EnableDragAndDrop { @@ -403,6 +415,10 @@ func (w *linuxWebviewWindow) run() { case WindowStateNormal: } + //if w.parent.options.IgnoreMouseEvents { + // windowIgnoreMouseEvents(w.window, w.webview, true) + //} + startURL, err := assetserver.GetStartURL(w.parent.options.URL) if err != nil { globalApplication.fatal(err.Error()) @@ -459,6 +475,11 @@ func (w *linuxWebviewWindow) relativePosition() (int, int) { func (w *linuxWebviewWindow) destroy() { w.parent.markAsDestroyed() + // Free menu + if w.gtkmenu != nil { + menuDestroy(w.gtkmenu) + w.gtkmenu = nil + } windowDestroy(w.window) } From 4cd4b46772f435ee29417f68e41f8177299bd83c Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 7 Feb 2024 22:19:33 +1100 Subject: [PATCH 056/369] [WIP] refactor CGO methods --- v3/pkg/application/application_linux.go | 72 +++--- v3/pkg/application/dialogs_linux.go | 4 +- v3/pkg/application/events_common_linux.go | 4 +- v3/pkg/application/linux_cgo.go | 255 ++++++++++++--------- v3/pkg/application/mainthread_linux.go | 2 +- v3/pkg/application/screen_linux.go | 6 +- v3/pkg/application/webview_window_linux.go | 173 ++------------ 7 files changed, 203 insertions(+), 313 deletions(-) diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index 2d50e988895..99981bd3345 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -34,7 +34,7 @@ type linuxApp struct { theme string } -func (l *linuxApp) GetFlags(options Options) map[string]any { +func (a *linuxApp) GetFlags(options Options) map[string]any { if options.Flags == nil { options.Flags = make(map[string]any) } @@ -45,32 +45,28 @@ func getNativeApplication() *linuxApp { return globalApplication.impl.(*linuxApp) } -func (l *linuxApp) hide() { - hideAllWindows(l.application) +func (a *linuxApp) hide() { + a.hideAllWindows() } -func (l *linuxApp) show() { - showAllWindows(l.application) +func (a *linuxApp) show() { + a.showAllWindows() } -func (l *linuxApp) on(eventID uint) { +func (a *linuxApp) on(eventID uint) { // TODO: Test register/unregister events //C.registerApplicationEvent(l.application, C.uint(eventID)) } -func (l *linuxApp) setIcon(icon []byte) { +func (a *linuxApp) setIcon(icon []byte) { log.Println("linuxApp.setIcon", "not implemented") } -func (l *linuxApp) name() string { +func (a *linuxApp) name() string { return appName() } -func (l *linuxApp) getCurrentWindowID() uint { - return getCurrentWindowID(l.application, l.windowMap) -} - type rnr struct { f func() } @@ -79,7 +75,7 @@ func (r rnr) run() { r.f() } -func (l *linuxApp) setApplicationMenu(menu *Menu) { +func (a *linuxApp) setApplicationMenu(menu *Menu) { // FIXME: How do we avoid putting a menu? if menu == nil { // Create a default menu @@ -88,55 +84,55 @@ func (l *linuxApp) setApplicationMenu(menu *Menu) { } } -func (l *linuxApp) run() error { +func (a *linuxApp) run() error { - l.parent.On(events.Linux.ApplicationStartup, func(evt *Event) { + a.parent.On(events.Linux.ApplicationStartup, func(evt *Event) { fmt.Println("events.Linux.ApplicationStartup received!") }) - l.setupCommonEvents() - l.monitorThemeChanges() - return appRun(l.application) + a.setupCommonEvents() + a.monitorThemeChanges() + return appRun(a.application) } -func (l *linuxApp) unregisterWindow(w windowPointer) { - l.windowMapLock.Lock() - delete(l.windowMap, w) - l.windowMapLock.Unlock() +func (a *linuxApp) unregisterWindow(w windowPointer) { + a.windowMapLock.Lock() + delete(a.windowMap, w) + a.windowMapLock.Unlock() // If this was the last window... - if len(l.windowMap) == 0 && !l.parent.options.Linux.DisableQuitOnLastWindowClosed { - l.destroy() + if len(a.windowMap) == 0 && !a.parent.options.Linux.DisableQuitOnLastWindowClosed { + a.destroy() } } -func (l *linuxApp) destroy() { +func (a *linuxApp) destroy() { if !globalApplication.shouldQuit() { return } globalApplication.cleanup() - appDestroy(l.application) + appDestroy(a.application) } -func (l *linuxApp) isOnMainThread() bool { +func (a *linuxApp) isOnMainThread() bool { return isOnMainThread() } // register our window to our parent mapping -func (l *linuxApp) registerWindow(window pointer, id uint) { - l.windowMapLock.Lock() - l.windowMap[windowPointer(window)] = id - l.windowMapLock.Unlock() +func (a *linuxApp) registerWindow(window pointer, id uint) { + a.windowMapLock.Lock() + a.windowMap[windowPointer(window)] = id + a.windowMapLock.Unlock() } -func (l *linuxApp) isDarkMode() bool { - return strings.Contains(l.theme, "dark") +func (a *linuxApp) isDarkMode() bool { + return strings.Contains(a.theme, "dark") } -func (l *linuxApp) monitorThemeChanges() { +func (a *linuxApp) monitorThemeChanges() { go func() { conn, err := dbus.ConnectSessionBus() if err != nil { - l.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err) + a.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err) return } defer conn.Close() @@ -169,10 +165,10 @@ func (l *linuxApp) monitorThemeChanges() { continue } - if theme != l.theme { - l.theme = theme + if theme != a.theme { + a.theme = theme event := newApplicationEvent(events.Common.ThemeChanged) - event.Context().setIsDarkMode(l.isDarkMode()) + event.Context().setIsDarkMode(a.isDarkMode()) applicationEvents <- event } diff --git a/v3/pkg/application/dialogs_linux.go b/v3/pkg/application/dialogs_linux.go index 49499dda14e..be480d17677 100644 --- a/v3/pkg/application/dialogs_linux.go +++ b/v3/pkg/application/dialogs_linux.go @@ -1,7 +1,7 @@ package application -func (l *linuxApp) showAboutDialog(title string, message string, icon []byte) { - window := globalApplication.getWindowForID(l.getCurrentWindowID()) +func (a *linuxApp) showAboutDialog(title string, message string, icon []byte) { + window := globalApplication.getWindowForID(a.getCurrentWindowID()) var parent uintptr if window != nil { parent, _ = window.(*WebviewWindow).NativeWindowHandle() diff --git a/v3/pkg/application/events_common_linux.go b/v3/pkg/application/events_common_linux.go index 530ac1563ab..e06fb8cfefc 100644 --- a/v3/pkg/application/events_common_linux.go +++ b/v3/pkg/application/events_common_linux.go @@ -9,11 +9,11 @@ var commonApplicationEventMap = map[events.ApplicationEventType]events.Applicati events.Linux.SystemThemeChanged: events.Common.ThemeChanged, } -func (l *linuxApp) setupCommonEvents() { +func (a *linuxApp) setupCommonEvents() { for sourceEvent, targetEvent := range commonApplicationEventMap { sourceEvent := sourceEvent targetEvent := targetEvent - l.parent.On(sourceEvent, func(event *Event) { + a.parent.On(sourceEvent, func(event *Event) { event.Id = uint(targetEvent) applicationEvents <- event }) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index beba773fe6f..dc921df2727 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -286,13 +286,13 @@ func appDestroy(application pointer) { C.g_application_quit((*C.GApplication)(application)) } -func contextMenuShow(window pointer, menu pointer, data *ContextMenuData) { +func (w *linuxWebviewWindow) contextMenuShow(menu pointer, data *ContextMenuData) { geometry := C.GdkRectangle{ x: C.int(data.X), y: C.int(data.Y), } event := C.GdkEvent{} - gdkWindow := C.gtk_widget_get_window((*C.GtkWidget)(window)) + gdkWindow := C.gtk_widget_get_window(w.gtkWidget()) C.gtk_menu_popup_at_rect( (*C.GtkMenu)(menu), gdkWindow, @@ -303,13 +303,13 @@ func contextMenuShow(window pointer, menu pointer, data *ContextMenuData) { ) } -func getCurrentWindowID(application pointer, windows map[windowPointer]uint) uint { +func (a *linuxApp) getCurrentWindowID() uint { // TODO: Add extra metadata to window and use it! - window := (*C.GtkWindow)(C.gtk_application_get_active_window((*C.GtkApplication)(application))) + window := (*C.GtkWindow)(C.gtk_application_get_active_window((*C.GtkApplication)(a.application))) if window == nil { return uint(1) } - identifier, ok := windows[window] + identifier, ok := a.windowMap[window] if ok { return identifier } @@ -317,9 +317,9 @@ func getCurrentWindowID(application pointer, windows map[windowPointer]uint) uin return uint(1) } -func getWindows(application pointer) []pointer { +func (a *linuxApp) getWindows() []pointer { result := []pointer{} - windows := C.gtk_application_get_windows((*C.GtkApplication)(application)) + windows := C.gtk_application_get_windows((*C.GtkApplication)(a.application)) for { result = append(result, pointer(windows.data)) windows = windows.next @@ -329,14 +329,14 @@ func getWindows(application pointer) []pointer { } } -func hideAllWindows(application pointer) { - for _, window := range getWindows(application) { +func (a *linuxApp) hideAllWindows() { + for _, window := range a.getWindows() { C.gtk_widget_hide((*C.GtkWidget)(window)) } } -func showAllWindows(application pointer) { - for _, window := range getWindows(application) { +func (a *linuxApp) showAllWindows() { + for _, window := range a.getWindows() { C.gtk_window_present((*C.GtkWindow)(window)) } } @@ -661,26 +661,27 @@ func widgetSetVisible(widget pointer, hidden bool) { } } -// window related functions -func windowClose(window pointer) { - C.gtk_window_close((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) close() { + C.gtk_window_close((*C.GtkWindow)(w.window)) + getNativeApplication().unregisterWindow(windowPointer(w.window)) } -func windowEnableDND(id uint, webview pointer) { +func (w *linuxWebviewWindow) enableDND() { + id := w.parent.id dnd := C.CString("text/uri-list") defer C.free(unsafe.Pointer(dnd)) targetentry := C.gtk_target_entry_new(dnd, 0, C.guint(id)) defer C.gtk_target_entry_free(targetentry) - C.gtk_drag_dest_set((*C.GtkWidget)(webview), C.GTK_DEST_DEFAULT_DROP, targetentry, 1, C.GDK_ACTION_COPY) + C.gtk_drag_dest_set((*C.GtkWidget)(w.webview), C.GTK_DEST_DEFAULT_DROP, targetentry, 1, C.GDK_ACTION_COPY) event := C.CString("drag-data-received") defer C.free(unsafe.Pointer(event)) windowId := C.uint(id) - C.signal_connect(unsafe.Pointer(webview), event, C.onDragNDrop, unsafe.Pointer(C.gpointer(&windowId))) + C.signal_connect(unsafe.Pointer(w.webview), event, C.onDragNDrop, unsafe.Pointer(C.gpointer(&windowId))) } -func windowExecJS(webview pointer, js string) { +func (w *linuxWebviewWindow) execJS(js string) { value := C.CString(js) - C.webkit_web_view_evaluate_javascript((*C.WebKitWebView)(webview), + C.webkit_web_view_evaluate_javascript((*C.WebKitWebView)(w.webview), value, C.long(len(js)), nil, @@ -715,8 +716,8 @@ func windowGetCurrentMonitor(window pointer) *C.GdkMonitor { return C.gdk_display_get_monitor_at_window(display, gdk_window) } -func windowGetCurrentMonitorGeometry(window pointer) (x int, y int, width int, height int, scale int) { - monitor := windowGetCurrentMonitor(window) +func (w *linuxWebviewWindow) getCurrentMonitorGeometry() (x int, y int, width int, height int, scale int) { + monitor := windowGetCurrentMonitor(w.window) if monitor == nil { return -1, -1, -1, -1, 1 } @@ -726,13 +727,6 @@ func windowGetCurrentMonitorGeometry(window pointer) (x int, y int, width int, h return int(result.x), int(result.y), int(result.width), int(result.height), scale } -func windowGetAbsolutePosition(window pointer) (int, int) { - var x C.int - var y C.int - C.gtk_window_get_position((*C.GtkWindow)(window), &x, &y) - return int(x), int(y) -} - func windowGetSize(window pointer) (int, int) { var windowWidth C.int var windowHeight C.int @@ -740,11 +734,11 @@ func windowGetSize(window pointer) (int, int) { return int(windowWidth), int(windowHeight) } -func windowGetRelativePosition(window pointer) (int, int) { - x, y := windowGetAbsolutePosition(window) +func (w *linuxWebviewWindow) relativePosition() (int, int) { + x, y := w.absolutePosition() // The position must be relative to the screen it is on // We need to get the screen it is on - monitor := windowGetCurrentMonitor(window) + monitor := windowGetCurrentMonitor(w.window) geometry := C.GdkRectangle{} C.gdk_monitor_get_geometry(monitor, &geometry) x = x - int(geometry.x) @@ -755,46 +749,52 @@ func windowGetRelativePosition(window pointer) (int, int) { return x, y } -func windowHide(window pointer) { - C.gtk_widget_hide((*C.GtkWidget)(window)) +func (w *linuxWebviewWindow) gtkWidget() *C.GtkWidget { + return (*C.GtkWidget)(w.window) } -func windowIsFullscreen(window pointer) bool { - gdkwindow := C.gtk_widget_get_window((*C.GtkWidget)(window)) - state := C.gdk_window_get_state(gdkwindow) +func (w *linuxWebviewWindow) hide() { + // save position + w.lastX, w.lastY = w.absolutePosition() + C.gtk_widget_hide(w.gtkWidget()) +} + +func (w *linuxWebviewWindow) isFullscreen() bool { + gdkWindow := C.gtk_widget_get_window((*C.GtkWidget)(w.window)) + state := C.gdk_window_get_state(gdkWindow) return state&C.GDK_WINDOW_STATE_FULLSCREEN > 0 } -func windowIsFocused(window pointer) bool { +func (w *linuxWebviewWindow) isFocused() bool { // returns true if window is focused - return C.gtk_window_has_toplevel_focus((*C.GtkWindow)(window)) == 1 + return C.gtk_window_has_toplevel_focus((*C.GtkWindow)(w.window)) == 1 } -func windowIsMaximized(window pointer) bool { - gdkwindow := C.gtk_widget_get_window((*C.GtkWidget)(window)) +func (w *linuxWebviewWindow) isMaximised() bool { + gdkwindow := C.gtk_widget_get_window((*C.GtkWidget)(w.window)) state := C.gdk_window_get_state(gdkwindow) return state&C.GDK_WINDOW_STATE_MAXIMIZED > 0 && state&C.GDK_WINDOW_STATE_FULLSCREEN == 0 } -func windowIsMinimized(window pointer) bool { - gdkwindow := C.gtk_widget_get_window((*C.GtkWidget)(window)) +func (w *linuxWebviewWindow) isMinimised() bool { + gdkwindow := C.gtk_widget_get_window((*C.GtkWidget)(w.window)) state := C.gdk_window_get_state(gdkwindow) return state&C.GDK_WINDOW_STATE_ICONIFIED > 0 } -func windowIsVisible(window pointer) bool { - if C.gtk_widget_is_visible((*C.GtkWidget)(window)) == 1 { +func (w *linuxWebviewWindow) isVisible() bool { + if C.gtk_widget_is_visible(w.gtkWidget()) == 1 { return true } return false } -func windowMaximize(window pointer) { - C.gtk_window_maximize((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) maximise() { + C.gtk_window_maximize((*C.GtkWindow)(w.window)) } -func windowMinimize(window pointer) { - C.gtk_window_iconify((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) minimise() { + C.gtk_window_iconify((*C.GtkWindow)(w.window)) } func windowNew(application pointer, menu pointer, windowId uint, gpuPolicy WebviewGpuPolicy) (window, webview, vbox pointer) { @@ -849,26 +849,24 @@ func windowNewWebview(parentId uint, gpuPolicy WebviewGpuPolicy) pointer { return pointer(webView) } -func windowPresent(window pointer) { - C.gtk_window_present((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) present() { + C.gtk_window_present((*C.GtkWindow)(w.window)) // gtk_window_unminimize ((*C.GtkWindow)(w.window)) /// gtk4 } -func windowReload(webview pointer, address string) { - uri := C.CString(address) - C.webkit_web_view_load_uri((*C.WebKitWebView)(webview), uri) - C.free(unsafe.Pointer(uri)) -} - -func windowResize(window pointer, width, height int) { +func (w *linuxWebviewWindow) setSize(width, height int) { C.gtk_window_resize( - (*C.GtkWindow)(window), + w.gtkWindow(), C.gint(width), C.gint(height)) } -func windowShow(window pointer) { - C.gtk_widget_show_all((*C.GtkWidget)(window)) +func (w *linuxWebviewWindow) show() { + if w.gtkWidget() == nil { + return + } + C.gtk_widget_show_all(w.gtkWidget()) + w.setAbsolutePosition(w.lastX, w.lastY) } func windowIgnoreMouseEvents(window pointer, webview pointer, ignore bool) { @@ -881,15 +879,27 @@ func windowIgnoreMouseEvents(window pointer, webview pointer, ignore bool) { C.webkit_web_view_set_editable((*C.WebKitWebView)(webview), C.gboolean(enable)) } -func windowSetBackgroundColour(vbox, webview pointer, colour RGBA) { +func (w *linuxWebviewWindow) webKitWebView() *C.WebKitWebView { + return (*C.WebKitWebView)(w.webview) +} + +func (w *linuxWebviewWindow) setBorderless(borderless bool) { + C.gtk_window_set_decorated(w.gtkWindow(), gtkBool(!borderless)) +} + +func (w *linuxWebviewWindow) setResizable(resizable bool) { + C.gtk_window_set_resizable(w.gtkWindow(), gtkBool(resizable)) +} + +func (w *linuxWebviewWindow) setBackgroundColour(colour RGBA) { rgba := C.GdkRGBA{C.double(colour.Red) / 255.0, C.double(colour.Green) / 255.0, C.double(colour.Blue) / 255.0, C.double(colour.Alpha) / 255.0} - C.webkit_web_view_set_background_color((*C.WebKitWebView)(webview), &rgba) + C.webkit_web_view_set_background_color((*C.WebKitWebView)(w.webview), &rgba) colour.Alpha = 255 cssStr := C.CString(fmt.Sprintf("#webview-box {background-color: rgba(%d, %d, %d, %1.1f);}", colour.Red, colour.Green, colour.Blue, float32(colour.Alpha)/255.0)) provider := C.gtk_css_provider_new() C.gtk_style_context_add_provider( - C.gtk_widget_get_style_context((*C.GtkWidget)(vbox)), + C.gtk_widget_get_style_context((*C.GtkWidget)(w.vbox)), (*C.GtkStyleProvider)(unsafe.Pointer(provider)), C.GTK_STYLE_PROVIDER_PRIORITY_USER) C.g_object_unref(C.gpointer(provider)) @@ -907,14 +917,14 @@ func windowSetGeometryHints(window pointer, minWidth, minHeight, maxWidth, maxHe C.gtk_window_set_geometry_hints((*C.GtkWindow)(window), nil, &size, C.GDK_HINT_MAX_SIZE|C.GDK_HINT_MIN_SIZE) } -func windowSetFrameless(window pointer, frameless bool) { - C.gtk_window_set_decorated((*C.GtkWindow)(window), gtkBool(!frameless)) +func (w *linuxWebviewWindow) setFrameless(frameless bool) { + C.gtk_window_set_decorated(w.gtkWindow(), gtkBool(!frameless)) // TODO: Deal with transparency for the titlebar if possible when !frameless // Perhaps we just make it undecorated and add a menu bar inside? } // TODO: confirm this is working properly -func windowSetHTML(webview pointer, html string) { +func (w *linuxWebviewWindow) setHTML(html string) { cHTML := C.CString(html) uri := C.CString("wails://") empty := C.CString("") @@ -922,39 +932,41 @@ func windowSetHTML(webview pointer, html string) { defer C.free(unsafe.Pointer(uri)) defer C.free(unsafe.Pointer(empty)) C.webkit_web_view_load_alternate_html( - (*C.WebKitWebView)(webview), + w.webKitWebView(), cHTML, uri, empty) } -func windowSetKeepAbove(window pointer, alwaysOnTop bool) { - C.gtk_window_set_keep_above((*C.GtkWindow)(window), gtkBool(alwaysOnTop)) +func (w *linuxWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) { + C.gtk_window_set_keep_above((*C.GtkWindow)(w.window), gtkBool(alwaysOnTop)) } -func windowSetResizable(window pointer, resizable bool) { - C.gtk_window_set_resizable((*C.GtkWindow)(window), gtkBool(resizable)) +func (w *linuxWebviewWindow) setTitle(title string) { + if !w.parent.options.Frameless { + cTitle := C.CString(title) + C.gtk_window_set_title(w.gtkWindow(), cTitle) + C.free(unsafe.Pointer(cTitle)) + } } -func windowSetTitle(window pointer, title string) { - cTitle := C.CString(title) - C.gtk_window_set_title((*C.GtkWindow)(window), cTitle) - C.free(unsafe.Pointer(cTitle)) +func (w *linuxWebviewWindow) gtkWindow() *C.GtkWindow { + return (*C.GtkWindow)(w.window) } -func windowSetTransparent(window pointer) { - screen := C.gtk_widget_get_screen((*C.GtkWidget)(window)) +func (w *linuxWebviewWindow) setTransparent() { + screen := C.gtk_widget_get_screen(w.gtkWidget()) visual := C.gdk_screen_get_rgba_visual(screen) if visual != nil && C.gdk_screen_is_composited(screen) == C.int(1) { - C.gtk_widget_set_app_paintable((*C.GtkWidget)(window), C.gboolean(1)) - C.gtk_widget_set_visual((*C.GtkWidget)(window), visual) + C.gtk_widget_set_app_paintable(w.gtkWidget(), C.gboolean(1)) + C.gtk_widget_set_visual(w.gtkWidget(), visual) } } -func windowSetURL(webview pointer, uri string) { +func (w *linuxWebviewWindow) setURL(uri string) { target := C.CString(uri) - C.webkit_web_view_load_uri((*C.WebKitWebView)(webview), target) + C.webkit_web_view_load_uri((*C.WebKitWebView)(w.webview), target) C.free(unsafe.Pointer(target)) } @@ -983,22 +995,23 @@ func handleLoadChanged(webview *C.WebKitWebView, event C.WebKitLoadEvent, data C } } -func windowSetupSignalHandlers(windowId uint, window, webview pointer, emit func(e events.WindowEventType)) { +func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventType)) { c := NewCalloc() defer c.Free() - winID := unsafe.Pointer(uintptr(C.uint(windowId))) + winID := unsafe.Pointer(uintptr(C.uint(w.parent.ID()))) // Set up the window close event - C.signal_connect(unsafe.Pointer(window), c.String("delete-event"), C.handleDeleteEvent, winID) - C.signal_connect(unsafe.Pointer(webview), c.String("load-changed"), C.handleLoadChanged, winID) + wv := unsafe.Pointer(w.webview) + C.signal_connect(unsafe.Pointer(w.window), c.String("delete-event"), C.handleDeleteEvent, winID) + C.signal_connect(wv, c.String("load-changed"), C.handleLoadChanged, winID) - contentManager := C.webkit_web_view_get_user_content_manager((*C.WebKitWebView)(webview)) + contentManager := C.webkit_web_view_get_user_content_manager(w.webKitWebView()) C.signal_connect(unsafe.Pointer(contentManager), c.String("script-message-received::external"), C.sendMessageToBackend, nil) - C.signal_connect(unsafe.Pointer(webview), c.String("button-press-event"), C.onButtonEvent, winID) - C.signal_connect(unsafe.Pointer(webview), c.String("button-release-event"), C.onButtonEvent, winID) - C.signal_connect(unsafe.Pointer(webview), c.String("key-press-event"), C.onKeyPressEvent, winID) + C.signal_connect(wv, c.String("button-press-event"), C.onButtonEvent, winID) + C.signal_connect(wv, c.String("button-release-event"), C.onButtonEvent, winID) + C.signal_connect(wv, c.String("key-press-event"), C.onKeyPressEvent, winID) } func windowShowDevTools(webview pointer) { @@ -1006,13 +1019,14 @@ func windowShowDevTools(webview pointer) { C.webkit_web_inspector_show(inspector) } -func windowStartDrag(window pointer, button uint, xroot int, yroot int, dragTime uint32) { +func (w *linuxWebviewWindow) startDrag() error { C.gtk_window_begin_move_drag( - (*C.GtkWindow)(window), - C.int(button), - C.int(xroot), - C.int(yroot), - C.uint32_t(dragTime)) + (*C.GtkWindow)(w.window), + C.int(w.drag.MouseButton), + C.int(w.drag.XRoot), + C.int(w.drag.YRoot), + C.uint32_t(w.drag.DragTime)) + return nil } func windowToggleDevTools(webview pointer) { @@ -1027,37 +1041,56 @@ func windowToggleDevTools(webview pointer) { C.webkit_settings_set_enable_developer_extras(settings, enabled) } -func windowUnfullscreen(window pointer) { - C.gtk_window_unfullscreen((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) unfullscreen() { + C.gtk_window_unfullscreen((*C.GtkWindow)(w.window)) + w.unmaximise() } -func windowUnmaximize(window pointer) { - C.gtk_window_unmaximize((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) unmaximise() { + C.gtk_window_unmaximize((*C.GtkWindow)(w.window)) } -func windowZoom(webview pointer) float64 { - return float64(C.webkit_web_view_get_zoom_level((*C.WebKitWebView)(webview))) +func (w *linuxWebviewWindow) getZoom() float64 { + return float64(C.webkit_web_view_get_zoom_level(w.webKitWebView())) } -// FIXME: ZoomIn/Out is assumed to be incorrect! -func windowZoomIn(webview pointer) { +func (w *linuxWebviewWindow) zoomIn() { + // FIXME: ZoomIn/Out is assumed to be incorrect! ZoomInFactor := 1.10 - windowZoomSet(webview, windowZoom(webview)*ZoomInFactor) + w.setZoom(w.getZoom() * ZoomInFactor) } -func windowZoomOut(webview pointer) { - ZoomOutFactor := -1.10 - windowZoomSet(webview, windowZoom(webview)*ZoomOutFactor) + +func (w *linuxWebviewWindow) zoomOut() { + ZoomInFactor := -1.10 + w.setZoom(w.getZoom() * ZoomInFactor) +} + +func (w *linuxWebviewWindow) zoomReset() { + w.setZoom(1.0) } -func windowZoomSet(webview pointer, zoom float64) { +func (w *linuxWebviewWindow) reload() { + uri := C.CString("wails://") + C.webkit_web_view_load_uri((*C.WebKitWebView)(w.webview), uri) + C.free(unsafe.Pointer(uri)) +} + +func (w *linuxWebviewWindow) setZoom(zoom float64) { if zoom < 1 { // 1.0 is the smallest allowable zoom = 1 } - C.webkit_web_view_set_zoom_level((*C.WebKitWebView)(webview), C.double(zoom)) + C.webkit_web_view_set_zoom_level(w.webKitWebView(), C.double(zoom)) +} + +func (w *linuxWebviewWindow) move(x, y int) { + C.gtk_window_move((*C.GtkWindow)(w.window), C.int(x), C.int(y)) } -func windowMove(window pointer, x, y int) { - C.gtk_window_move((*C.GtkWindow)(window), C.int(x), C.int(y)) +func (w *linuxWebviewWindow) absolutePosition() (int, int) { + var x C.int + var y C.int + C.gtk_window_get_position((*C.GtkWindow)(w.window), &x, &y) + return int(x), int(y) } // FIXME Change this to reflect mouse button! diff --git a/v3/pkg/application/mainthread_linux.go b/v3/pkg/application/mainthread_linux.go index 2a5ff3e2cb3..a718688bc4f 100644 --- a/v3/pkg/application/mainthread_linux.go +++ b/v3/pkg/application/mainthread_linux.go @@ -2,7 +2,7 @@ package application -func (l *linuxApp) dispatchOnMainThread(id uint) { +func (a *linuxApp) dispatchOnMainThread(id uint) { dispatchOnMainThread(id) } diff --git a/v3/pkg/application/screen_linux.go b/v3/pkg/application/screen_linux.go index 526752aceba..d93cfbd927e 100644 --- a/v3/pkg/application/screen_linux.go +++ b/v3/pkg/application/screen_linux.go @@ -7,17 +7,17 @@ import ( "sync" ) -func (l *linuxApp) getPrimaryScreen() (*Screen, error) { +func (a *linuxApp) getPrimaryScreen() (*Screen, error) { return nil, fmt.Errorf("not implemented") } -func (l *linuxApp) getScreens() ([]*Screen, error) { +func (a *linuxApp) getScreens() ([]*Screen, error) { var wg sync.WaitGroup var screens []*Screen var err error wg.Add(1) InvokeSync(func() { - screens, err = getScreens(l.application) + screens, err = getScreens(a.application) wg.Done() }) wg.Wait() diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 80d5b9831bb..261287d137c 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -9,6 +9,7 @@ import ( "github.com/wailsapp/wails/v3/internal/capabilities" "github.com/wailsapp/wails/v3/internal/runtime" "github.com/wailsapp/wails/v3/pkg/events" + "math" ) var showDevTools = func(window pointer) {} @@ -41,26 +42,17 @@ var ( registered bool = false // avoid 'already registered message' about 'wails://' ) -func (w *linuxWebviewWindow) startDrag() error { - windowStartDrag(w.window, w.drag.MouseButton, w.drag.XRoot, w.drag.YRoot, w.drag.DragTime) - return nil -} - func (w *linuxWebviewWindow) endDrag(button uint, x, y int) { w.drag.XRoot = 0.0 w.drag.YRoot = 0.0 w.drag.DragTime = 0 } -func (w *linuxWebviewWindow) enableDND() { - windowEnableDND(w.parent.id, w.webview) -} - func (w *linuxWebviewWindow) connectSignals() { cb := func(e events.WindowEventType) { w.parent.emit(e) } - windowSetupSignalHandlers(w.parent.id, w.window, w.webview, cb) + w.setupSignalHandlers(cb) } func (w *linuxWebviewWindow) openContextMenu(menu *Menu, data *ContextMenuData) { @@ -74,23 +66,11 @@ func (w *linuxWebviewWindow) openContextMenu(menu *Menu, data *ContextMenuData) } native := ctxMenu.menu.impl.(*linuxMenu).native - contextMenuShow(w.window, native, data) -} - -func (w *linuxWebviewWindow) getZoom() float64 { - return windowZoom(w.webview) -} - -func (w *linuxWebviewWindow) setZoom(zoom float64) { - windowZoomSet(w.webview, zoom) -} - -func (w *linuxWebviewWindow) setFrameless(frameless bool) { - windowSetFrameless(w.window, frameless) + w.contextMenuShow(native, data) } func (w *linuxWebviewWindow) getScreen() (*Screen, error) { - mx, my, width, height, scale := windowGetCurrentMonitorGeometry(w.window) + mx, my, width, height, scale := w.getCurrentMonitorGeometry() return &Screen{ ID: fmt.Sprintf("%d", w.id), // A unique identifier for the display Name: w.parent.Name(), // The name of the display @@ -106,47 +86,27 @@ func (w *linuxWebviewWindow) getScreen() (*Screen, error) { } func (w *linuxWebviewWindow) focus() { - windowPresent(w.window) -} - -func (w *linuxWebviewWindow) show() { - windowShow(w.window) - w.setAbsolutePosition(w.lastX, w.lastY) -} - -func (w *linuxWebviewWindow) hide() { - // save position - w.lastX, w.lastY = windowGetAbsolutePosition(w.window) - windowHide(w.window) + w.present() } func (w *linuxWebviewWindow) isNormal() bool { return !w.isMinimised() && !w.isMaximised() && !w.isFullscreen() } -func (w *linuxWebviewWindow) isVisible() bool { - return windowIsVisible(w.window) -} - func (w *linuxWebviewWindow) setFullscreenButtonEnabled(enabled bool) { // C.setFullscreenButtonEnabled(w.nsWindow, C.bool(enabled)) fmt.Println("setFullscreenButtonEnabled - not implemented") } func (w *linuxWebviewWindow) disableSizeConstraints() { - x, y, width, height, scale := windowGetCurrentMonitorGeometry(w.window) + x, y, width, height, scale := w.getCurrentMonitorGeometry() w.setMinMaxSize(x, y, width*scale, height*scale) } -func (w *linuxWebviewWindow) unfullscreen() { - windowUnfullscreen(w.window) - w.unmaximise() -} - func (w *linuxWebviewWindow) fullscreen() { w.maximise() //w.lastWidth, w.lastHeight = w.size() - x, y, width, height, scale := windowGetCurrentMonitorGeometry(w.window) + x, y, width, height, scale := w.getCurrentMonitorGeometry() if x == -1 && y == -1 && width == -1 && height == -1 { return } @@ -157,19 +117,7 @@ func (w *linuxWebviewWindow) fullscreen() { } func (w *linuxWebviewWindow) unminimise() { - windowPresent(w.window) -} - -func (w *linuxWebviewWindow) unmaximise() { - windowUnmaximize(w.window) -} - -func (w *linuxWebviewWindow) maximise() { - windowMaximize(w.window) -} - -func (w *linuxWebviewWindow) minimise() { - windowMinimize(w.window) + w.present() } func (w *linuxWebviewWindow) flash(enabled bool) { @@ -189,59 +137,22 @@ func (w *linuxWebviewWindow) windowZoom() { w.zoom() // FIXME> This should be removed } -func (w *linuxWebviewWindow) close() { - windowClose(w.window) - getNativeApplication().unregisterWindow(windowPointer(w.window)) -} - -func (w *linuxWebviewWindow) zoomIn() { - windowZoomIn(w.webview) -} - -func (w *linuxWebviewWindow) zoomOut() { - windowZoomOut(w.webview) -} - -func (w *linuxWebviewWindow) zoomReset() { - windowZoomSet(w.webview, 1.0) -} - -func (w *linuxWebviewWindow) reload() { - windowReload(w.webview, "wails://") -} - func (w *linuxWebviewWindow) forceReload() { w.reload() } func (w *linuxWebviewWindow) center() { - x, y, width, height, _ := windowGetCurrentMonitorGeometry(w.window) + x, y, width, height, _ := w.getCurrentMonitorGeometry() if x == -1 && y == -1 && width == -1 && height == -1 { return } windowWidth, windowHeight := windowGetSize(w.window) - newX := ((width - int(windowWidth)) / 2) + x - newY := ((height - int(windowHeight)) / 2) + y + newX := ((width - windowWidth) / 2) + x + newY := ((height - windowHeight) / 2) + y // Place the window at the center of the monitor - windowMove(w.window, newX, newY) -} - -func (w *linuxWebviewWindow) isMinimised() bool { - return windowIsMinimized(w.window) -} - -func (w *linuxWebviewWindow) isMaximised() bool { - return windowIsMaximized(w.window) -} - -func (w *linuxWebviewWindow) isFocused() bool { - return windowIsFocused(w.window) -} - -func (w *linuxWebviewWindow) isFullscreen() bool { - return windowIsFullscreen(w.window) + w.move(newX, newY) } func (w *linuxWebviewWindow) restore() { @@ -249,18 +160,6 @@ func (w *linuxWebviewWindow) restore() { // FIXME: never called! - remove from webviewImpl interface } -func (w *linuxWebviewWindow) execJS(js string) { - windowExecJS(w.webview, js) -} - -func (w *linuxWebviewWindow) setURL(uri string) { - windowSetURL(w.webview, uri) -} - -func (w *linuxWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) { - windowSetKeepAbove(w.window, alwaysOnTop) -} - func newWindowImpl(parent *WebviewWindow) *linuxWebviewWindow { // (*C.struct__GtkWidget)(m.native) //var menubar *C.struct__GtkWidget @@ -272,16 +171,6 @@ func newWindowImpl(parent *WebviewWindow) *linuxWebviewWindow { return result } -func (w *linuxWebviewWindow) setTitle(title string) { - if !w.parent.options.Frameless { - windowSetTitle(w.window, title) - } -} - -func (w *linuxWebviewWindow) setSize(width, height int) { - windowResize(w.window, width, height) -} - func (w *linuxWebviewWindow) setMinMaxSize(minWidth, minHeight, maxWidth, maxHeight int) { if minWidth == 0 { minWidth = -1 @@ -290,10 +179,10 @@ func (w *linuxWebviewWindow) setMinMaxSize(minWidth, minHeight, maxWidth, maxHei minHeight = -1 } if maxWidth == 0 { - maxWidth = -1 + maxWidth = math.MaxInt } if maxHeight == 0 { - maxHeight = -1 + maxHeight = math.MaxInt } windowSetGeometryHints(w.window, minWidth, minHeight, maxWidth, maxHeight) } @@ -306,10 +195,6 @@ func (w *linuxWebviewWindow) setMaxSize(width, height int) { w.setMinMaxSize(w.parent.options.MinWidth, w.parent.options.MinHeight, width, height) } -func (w *linuxWebviewWindow) setResizable(resizable bool) { - windowSetResizable(w.window, resizable) -} - func (w *linuxWebviewWindow) showDevTools() { windowShowDevTools(w.webview) } @@ -323,8 +208,8 @@ func (w *linuxWebviewWindow) size() (int, int) { } func (w *linuxWebviewWindow) setRelativePosition(x, y int) { - mx, my, _, _, _ := windowGetCurrentMonitorGeometry(w.window) - windowMove(w.window, x+mx, y+my) + mx, my, _, _, _ := w.getCurrentMonitorGeometry() + w.move(x+mx, y+my) } func (w *linuxWebviewWindow) width() int { @@ -339,13 +224,7 @@ func (w *linuxWebviewWindow) height() int { func (w *linuxWebviewWindow) setAbsolutePosition(x int, y int) { // Set the window's absolute position - windowMove(w.window, x, y) -} - -func (w *linuxWebviewWindow) absolutePosition() (int, int) { - var x, y int - x, y = windowGetAbsolutePosition(w.window) - return x, y + w.move(x, y) } func (w *linuxWebviewWindow) run() { @@ -459,20 +338,6 @@ func (w *linuxWebviewWindow) run() { } } -func (w *linuxWebviewWindow) setTransparent() { - windowSetTransparent(w.window) -} - -func (w *linuxWebviewWindow) setBackgroundColour(colour RGBA) { - windowSetBackgroundColour(w.vbox, w.webview, colour) -} - -func (w *linuxWebviewWindow) relativePosition() (int, int) { - var x, y int - x, y = windowGetRelativePosition(w.window) - return x, y -} - func (w *linuxWebviewWindow) destroy() { w.parent.markAsDestroyed() // Free menu @@ -487,10 +352,6 @@ func (w *linuxWebviewWindow) setEnabled(enabled bool) { widgetSetSensitive(w.window, enabled) } -func (w *linuxWebviewWindow) setHTML(html string) { - windowSetHTML(w.webview, html) -} - func (w *linuxWebviewWindow) startResize(border string) error { // FIXME: what do we need to do here? return nil From a34ccbff334015e42a56cf1644e67746bc4a1faa Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 9 Feb 2024 20:06:38 +1100 Subject: [PATCH 057/369] ToggleDevTools -> OpenDevTools More refactor CGO methods. --- v3/examples/window/main.go | 5 ++ v3/pkg/application/linux_cgo.go | 58 +++++++++++-------- v3/pkg/application/linux_purego.go | 2 +- v3/pkg/application/menuitem.go | 4 +- v3/pkg/application/menuitem_darwin.go | 11 ---- v3/pkg/application/menuitem_dev.go | 6 +- v3/pkg/application/menuitem_linux.go | 11 ---- v3/pkg/application/menuitem_production.go | 2 +- v3/pkg/application/roles.go | 2 +- v3/pkg/application/roles_dev.go | 2 +- v3/pkg/application/webview_window.go | 6 +- v3/pkg/application/webview_window_darwin.go | 6 +- .../application/webview_window_darwin_dev.go | 17 +----- .../webview_window_darwin_production.go | 1 + v3/pkg/application/webview_window_linux.go | 47 +-------------- .../application/webview_window_linux_dev.go | 11 ++++ .../webview_window_linux_devtools.go | 9 --- .../webview_window_linux_production.go | 7 +++ .../webview_window_windows_devtools.go | 2 +- .../webview_window_windows_production.go | 2 +- v3/pkg/application/window.go | 2 +- 21 files changed, 81 insertions(+), 132 deletions(-) create mode 100644 v3/pkg/application/webview_window_linux_dev.go delete mode 100644 v3/pkg/application/webview_window_linux_devtools.go create mode 100644 v3/pkg/application/webview_window_linux_production.go diff --git a/v3/examples/window/main.go b/v3/examples/window/main.go index 4a31eaa0a04..bfa6d22522a 100644 --- a/v3/examples/window/main.go +++ b/v3/examples/window/main.go @@ -439,6 +439,11 @@ func main() { w.SetEnabled(true) }) }) + stateMenu.Add("Open Dev Tools").OnClick(func(ctx *application.Context) { + currentWindow(func(w *application.WebviewWindow) { + w.OpenDevTools() + }) + }) if runtime.GOOS == "windows" { stateMenu.Add("Flash Start").OnClick(func(ctx *application.Context) { diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index dc921df2727..5c664f395e4 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -644,13 +644,14 @@ func getScreens(app pointer) ([]*Screen, error) { } // widgets -func widgetSetSensitive(widget pointer, enabled bool) { - value := C.int(0) + +func (w *linuxWebviewWindow) setEnabled(enabled bool) { + var value C.int if enabled { value = C.int(1) } - C.gtk_widget_set_sensitive((*C.GtkWidget)(widget), value) + C.gtk_widget_set_sensitive(w.gtkWidget(), value) } func widgetSetVisible(widget pointer, hidden bool) { @@ -692,32 +693,41 @@ func (w *linuxWebviewWindow) execJS(js string) { C.free(unsafe.Pointer(value)) } -func windowDestroy(window pointer) { - // Should this truly 'destroy' ? - C.gtk_window_close((*C.GtkWindow)(window)) - //C.gtk_widget_destroy((*C.GtkWidget)(window)) -} - -func menuDestroy(gtkMenu pointer) { - C.gtk_widget_destroy((*C.GtkWidget)(gtkMenu)) +func (w *linuxWebviewWindow) destroy() { + w.parent.markAsDestroyed() + // Free menu + if w.gtkmenu != nil { + C.gtk_widget_destroy((*C.GtkWidget)(w.gtkmenu)) + w.gtkmenu = nil + } + w.destroy() } -func windowFullscreen(window pointer) { - C.gtk_window_fullscreen((*C.GtkWindow)(window)) +func (w *linuxWebviewWindow) fullscreen() { + w.maximise() + //w.lastWidth, w.lastHeight = w.size() + x, y, width, height, scale := w.getCurrentMonitorGeometry() + if x == -1 && y == -1 && width == -1 && height == -1 { + return + } + w.setMinMaxSize(0, 0, width*scale, height*scale) + w.setSize(width*scale, height*scale) + C.gtk_window_fullscreen(w.gtkWindow()) + w.setRelativePosition(0, 0) } -func windowGetCurrentMonitor(window pointer) *C.GdkMonitor { +func (w *linuxWebviewWindow) getCurrentMonitor() *C.GdkMonitor { // Get the monitor that the window is currently on - display := C.gtk_widget_get_display((*C.GtkWidget)(window)) - gdk_window := C.gtk_widget_get_window((*C.GtkWidget)(window)) - if gdk_window == nil { + display := C.gtk_widget_get_display(w.gtkWidget()) + gdkWindow := C.gtk_widget_get_window(w.gtkWidget()) + if gdkWindow == nil { return nil } - return C.gdk_display_get_monitor_at_window(display, gdk_window) + return C.gdk_display_get_monitor_at_window(display, gdkWindow) } func (w *linuxWebviewWindow) getCurrentMonitorGeometry() (x int, y int, width int, height int, scale int) { - monitor := windowGetCurrentMonitor(w.window) + monitor := w.getCurrentMonitor() if monitor == nil { return -1, -1, -1, -1, 1 } @@ -727,10 +737,10 @@ func (w *linuxWebviewWindow) getCurrentMonitorGeometry() (x int, y int, width in return int(result.x), int(result.y), int(result.width), int(result.height), scale } -func windowGetSize(window pointer) (int, int) { +func (w *linuxWebviewWindow) size() (int, int) { var windowWidth C.int var windowHeight C.int - C.gtk_window_get_size((*C.GtkWindow)(window), &windowWidth, &windowHeight) + C.gtk_window_get_size(w.gtkWindow(), &windowWidth, &windowHeight) return int(windowWidth), int(windowHeight) } @@ -738,7 +748,7 @@ func (w *linuxWebviewWindow) relativePosition() (int, int) { x, y := w.absolutePosition() // The position must be relative to the screen it is on // We need to get the screen it is on - monitor := windowGetCurrentMonitor(w.window) + monitor := w.getCurrentMonitor() geometry := C.GdkRectangle{} C.gdk_monitor_get_geometry(monitor, &geometry) x = x - int(geometry.x) @@ -1014,7 +1024,7 @@ func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventT C.signal_connect(wv, c.String("key-press-event"), C.onKeyPressEvent, winID) } -func windowShowDevTools(webview pointer) { +func openDevTools(webview pointer) { inspector := C.webkit_web_view_get_inspector((*C.WebKitWebView)(webview)) C.webkit_web_inspector_show(inspector) } @@ -1029,7 +1039,7 @@ func (w *linuxWebviewWindow) startDrag() error { return nil } -func windowToggleDevTools(webview pointer) { +func enableDevTools(webview pointer) { settings := C.webkit_web_view_get_settings((*C.WebKitWebView)(webview)) enabled := C.webkit_settings_get_enable_developer_extras(settings) switch enabled { diff --git a/v3/pkg/application/linux_purego.go b/v3/pkg/application/linux_purego.go index 682bf195eda..5c58ae57854 100644 --- a/v3/pkg/application/linux_purego.go +++ b/v3/pkg/application/linux_purego.go @@ -976,7 +976,7 @@ func windowSetupSignalHandlers(windowId uint, window, webview pointer, emit func */ } -func windowToggleDevTools(webview pointer) { +func windowOpenDevTools(webview pointer) { settings := webkitWebViewGetSettings(pointer(webview)) webkitSettingsSetEnableDeveloperExtras( settings, diff --git a/v3/pkg/application/menuitem.go b/v3/pkg/application/menuitem.go index 7e0910a4df9..1f05874e8c6 100644 --- a/v3/pkg/application/menuitem.go +++ b/v3/pkg/application/menuitem.go @@ -167,8 +167,8 @@ func newRole(role Role) *MenuItem { return newForceReloadMenuItem() case ToggleFullscreen: return newToggleFullscreenMenuItem() - case ShowDevTools: - return newShowDevToolsMenuItem() + case OpenDevTools: + return newOpenDevToolsMenuItem() case ResetZoom: return newZoomResetMenuItem() case ZoomIn: diff --git a/v3/pkg/application/menuitem_darwin.go b/v3/pkg/application/menuitem_darwin.go index 714851bb533..3b25b56e2e7 100644 --- a/v3/pkg/application/menuitem_darwin.go +++ b/v3/pkg/application/menuitem_darwin.go @@ -576,17 +576,6 @@ func newToggleFullscreenMenuItem() *MenuItem { return result } -func newToggleDevToolsMenuItem() *MenuItem { - return newMenuItem("Toggle Developer Tools"). - SetAccelerator("Alt+Command+I"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.CurrentWindow() - if currentWindow != nil { - currentWindow.ToggleDevTools() - } - }) -} - func newZoomResetMenuItem() *MenuItem { // reset zoom menu item return newMenuItem("Actual Size"). diff --git a/v3/pkg/application/menuitem_dev.go b/v3/pkg/application/menuitem_dev.go index 23b0395cd18..7375b117dfe 100644 --- a/v3/pkg/application/menuitem_dev.go +++ b/v3/pkg/application/menuitem_dev.go @@ -2,13 +2,13 @@ package application -func newShowDevToolsMenuItem() *MenuItem { - return newMenuItem("Show Developer Tools"). +func newOpenDevToolsMenuItem() *MenuItem { + return newMenuItem("Open Developer Tools"). SetAccelerator("Alt+Command+I"). OnClick(func(ctx *Context) { currentWindow := globalApplication.CurrentWindow() if currentWindow != nil { - currentWindow.ToggleDevTools() + currentWindow.OpenDevTools() } }) } diff --git a/v3/pkg/application/menuitem_linux.go b/v3/pkg/application/menuitem_linux.go index 058b586092d..abdd8fe0551 100644 --- a/v3/pkg/application/menuitem_linux.go +++ b/v3/pkg/application/menuitem_linux.go @@ -294,17 +294,6 @@ func newToggleFullscreenMenuItem() *MenuItem { return result } -func newToggleDevToolsMenuItem() *MenuItem { - return newMenuItem("Toggle Developer Tools"). - SetAccelerator("Alt+Command+I"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.CurrentWindow() - if currentWindow != nil { - currentWindow.ToggleDevTools() - } - }) -} - func newZoomResetMenuItem() *MenuItem { // reset zoom menu item return newMenuItem("Actual Size"). diff --git a/v3/pkg/application/menuitem_production.go b/v3/pkg/application/menuitem_production.go index 553338e879f..387b9d06cb1 100644 --- a/v3/pkg/application/menuitem_production.go +++ b/v3/pkg/application/menuitem_production.go @@ -2,6 +2,6 @@ package application -func newShowDevToolsMenuItem() *MenuItem { +func newOpenDevToolsMenuItem() *MenuItem { return nil } diff --git a/v3/pkg/application/roles.go b/v3/pkg/application/roles.go index c096092735d..bce6b5c2c68 100644 --- a/v3/pkg/application/roles.go +++ b/v3/pkg/application/roles.go @@ -36,7 +36,7 @@ const ( Close Role = iota Reload Role = iota ForceReload Role = iota - ShowDevTools Role = iota + OpenDevTools Role = iota ResetZoom Role = iota ZoomIn Role = iota ZoomOut Role = iota diff --git a/v3/pkg/application/roles_dev.go b/v3/pkg/application/roles_dev.go index 6b0b1acc480..1c03e398dd7 100644 --- a/v3/pkg/application/roles_dev.go +++ b/v3/pkg/application/roles_dev.go @@ -3,5 +3,5 @@ package application func addDevToolMenuItem(viewMenu *Menu) { - viewMenu.AddRole(ShowDevTools) + viewMenu.AddRole(OpenDevTools) } diff --git a/v3/pkg/application/webview_window.go b/v3/pkg/application/webview_window.go index 833ba7a91d8..b08f39008f4 100644 --- a/v3/pkg/application/webview_window.go +++ b/v3/pkg/application/webview_window.go @@ -40,7 +40,7 @@ type ( destroy() reload() forceReload() - toggleDevTools() + openDevTools() zoomReset() zoomIn() zoomOut() @@ -817,11 +817,11 @@ func (w *WebviewWindow) ToggleMaximise() { }) } -func (w *WebviewWindow) ToggleDevTools() { +func (w *WebviewWindow) OpenDevTools() { if w.impl == nil && !w.isDestroyed() { return } - InvokeSync(w.impl.toggleDevTools) + InvokeSync(w.impl.openDevTools) } // ZoomReset resets the zoom level of the webview content to 100% diff --git a/v3/pkg/application/webview_window_darwin.go b/v3/pkg/application/webview_window_darwin.go index 156dba789f6..b185e189fdc 100644 --- a/v3/pkg/application/webview_window_darwin.go +++ b/v3/pkg/application/webview_window_darwin.go @@ -761,8 +761,6 @@ import ( "github.com/wailsapp/wails/v3/pkg/events" ) -var showDevTools = func(window unsafe.Pointer) {} - type macosWebviewWindow struct { nsWindow unsafe.Pointer parent *WebviewWindow @@ -906,8 +904,8 @@ func (w *macosWebviewWindow) zoomReset() { C.windowZoomReset(w.nsWindow) } -func (w *macosWebviewWindow) toggleDevTools() { - showDevTools(w.nsWindow) +func (w *macosWebviewWindow) openDevTools() { + openDevTools(w.nsWindow) } func (w *macosWebviewWindow) reload() { diff --git a/v3/pkg/application/webview_window_darwin_dev.go b/v3/pkg/application/webview_window_darwin_dev.go index 4e76c5a57b0..41ddfcd0cf1 100644 --- a/v3/pkg/application/webview_window_darwin_dev.go +++ b/v3/pkg/application/webview_window_darwin_dev.go @@ -19,15 +19,7 @@ package application - (_WKInspector *)_inspector; @end -//void showDevTools(void *window) { -// // get main window -// WebviewWindow* nsWindow = (WebviewWindow*)window; -// dispatch_async(dispatch_get_main_queue(), ^{ -// [nsWindow.webView._inspector show]; -// }); -//} - -void showDevTools(void *window) { +void openDevTools(void *window) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= 120000 dispatch_async(dispatch_get_main_queue(), ^{ if (@available(macOS 12.0, *)) { @@ -55,12 +47,9 @@ void windowEnableDevTools(void* nsWindow) { */ import "C" -import "unsafe" -func init() { - showDevTools = func(window unsafe.Pointer) { - C.showDevTools(window) - } +func (w *macosWebviewWindow) openDevTools() { + openDevTools(w.nsWindow) } func (w *macosWebviewWindow) enableDevTools() { diff --git a/v3/pkg/application/webview_window_darwin_production.go b/v3/pkg/application/webview_window_darwin_production.go index e0a5576e5ac..96e2de74ce9 100644 --- a/v3/pkg/application/webview_window_darwin_production.go +++ b/v3/pkg/application/webview_window_darwin_production.go @@ -3,3 +3,4 @@ package application func (w *macosWebviewWindow) enableDevTools() {} +func (w *macosWebviewWindow) openDevTools() {} diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 261287d137c..1309fa7b86e 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -12,8 +12,6 @@ import ( "math" ) -var showDevTools = func(window pointer) {} - type dragInfo struct { XRoot int YRoot int @@ -103,19 +101,6 @@ func (w *linuxWebviewWindow) disableSizeConstraints() { w.setMinMaxSize(x, y, width*scale, height*scale) } -func (w *linuxWebviewWindow) fullscreen() { - w.maximise() - //w.lastWidth, w.lastHeight = w.size() - x, y, width, height, scale := w.getCurrentMonitorGeometry() - if x == -1 && y == -1 && width == -1 && height == -1 { - return - } - w.setMinMaxSize(0, 0, width*scale, height*scale) - w.setSize(width*scale, height*scale) - windowFullscreen(w.window) - w.setRelativePosition(0, 0) -} - func (w *linuxWebviewWindow) unminimise() { w.present() } @@ -146,7 +131,7 @@ func (w *linuxWebviewWindow) center() { if x == -1 && y == -1 && width == -1 && height == -1 { return } - windowWidth, windowHeight := windowGetSize(w.window) + windowWidth, windowHeight := w.size() newX := ((width - windowWidth) / 2) + x newY := ((height - windowHeight) / 2) + y @@ -195,18 +180,6 @@ func (w *linuxWebviewWindow) setMaxSize(width, height int) { w.setMinMaxSize(w.parent.options.MinWidth, w.parent.options.MinHeight, width, height) } -func (w *linuxWebviewWindow) showDevTools() { - windowShowDevTools(w.webview) -} - -func (w *linuxWebviewWindow) toggleDevTools() { - showDevTools(w.webview) -} - -func (w *linuxWebviewWindow) size() (int, int) { - return windowGetSize(w.window) -} - func (w *linuxWebviewWindow) setRelativePosition(x, y int) { mx, my, _, _, _ := w.getCurrentMonitorGeometry() w.move(x+mx, y+my) @@ -331,27 +304,13 @@ func (w *linuxWebviewWindow) run() { } } if w.parent.options.DevToolsEnabled || globalApplication.isDebugMode { - w.toggleDevTools() + w.enableDevTools() if w.parent.options.OpenInspectorOnStartup { - w.showDevTools() + w.openDevTools() } } } -func (w *linuxWebviewWindow) destroy() { - w.parent.markAsDestroyed() - // Free menu - if w.gtkmenu != nil { - menuDestroy(w.gtkmenu) - w.gtkmenu = nil - } - windowDestroy(w.window) -} - -func (w *linuxWebviewWindow) setEnabled(enabled bool) { - widgetSetSensitive(w.window, enabled) -} - func (w *linuxWebviewWindow) startResize(border string) error { // FIXME: what do we need to do here? return nil diff --git a/v3/pkg/application/webview_window_linux_dev.go b/v3/pkg/application/webview_window_linux_dev.go new file mode 100644 index 00000000000..3f34a6e64b1 --- /dev/null +++ b/v3/pkg/application/webview_window_linux_dev.go @@ -0,0 +1,11 @@ +//go:build linux && !production + +package application + +func (w *linuxWebviewWindow) openDevTools() { + openDevTools(w.webview) +} + +func (w *linuxWebviewWindow) enableDevTools() { + enableDevTools(w.webview) +} diff --git a/v3/pkg/application/webview_window_linux_devtools.go b/v3/pkg/application/webview_window_linux_devtools.go deleted file mode 100644 index eb883ae24fc..00000000000 --- a/v3/pkg/application/webview_window_linux_devtools.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build linux && !production - -package application - -func init() { - showDevTools = func(wv pointer) { - windowToggleDevTools(wv) - } -} diff --git a/v3/pkg/application/webview_window_linux_production.go b/v3/pkg/application/webview_window_linux_production.go new file mode 100644 index 00000000000..c65520b8ee3 --- /dev/null +++ b/v3/pkg/application/webview_window_linux_production.go @@ -0,0 +1,7 @@ +//go:build linux && production && !devtools + +package application + +func (w *linuxWebviewWindow) openDevTools() {} + +func (w *linuxWebviewWindow) enableDevTools() {} diff --git a/v3/pkg/application/webview_window_windows_devtools.go b/v3/pkg/application/webview_window_windows_devtools.go index 54a799bf94e..2ee7ea1a34b 100644 --- a/v3/pkg/application/webview_window_windows_devtools.go +++ b/v3/pkg/application/webview_window_windows_devtools.go @@ -4,7 +4,7 @@ package application import "github.com/wailsapp/go-webview2/pkg/edge" -func (w *windowsWebviewWindow) toggleDevTools() { +func (w *windowsWebviewWindow) openDevTools() { w.chromium.OpenDevToolsWindow() } diff --git a/v3/pkg/application/webview_window_windows_production.go b/v3/pkg/application/webview_window_windows_production.go index 0dd2fff457b..55a9d2ad25e 100644 --- a/v3/pkg/application/webview_window_windows_production.go +++ b/v3/pkg/application/webview_window_windows_production.go @@ -4,7 +4,7 @@ package application import "github.com/wailsapp/go-webview2/pkg/edge" -func (w *windowsWebviewWindow) toggleDevTools() {} +func (w *windowsWebviewWindow) openDevTools() {} func (w *windowsWebviewWindow) enableDevTools(settings *edge.ICoreWebViewSettings) { err := settings.PutAreDevToolsEnabled(false) diff --git a/v3/pkg/application/window.go b/v3/pkg/application/window.go index 2398cd3682b..ce807944417 100644 --- a/v3/pkg/application/window.go +++ b/v3/pkg/application/window.go @@ -65,7 +65,7 @@ type Window interface { SetZoom(magnification float64) Window Show() Window Size() (width int, height int) - ToggleDevTools() + OpenDevTools() ToggleFullscreen() ToggleMaximise() UnFullscreen() From b6c5d90c9d2213a91a9376a500546ee371235598 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 9 Feb 2024 21:31:41 +1100 Subject: [PATCH 058/369] Window Flash for Linux Set Min/Max window buttons --- v3/examples/window/main.go | 6 ++++-- v3/pkg/application/linux_cgo.go | 5 +++++ v3/pkg/application/webview_window.go | 22 ++++++++++++++++++++ v3/pkg/application/webview_window_darwin.go | 18 +++++++++++++--- v3/pkg/application/webview_window_linux.go | 12 +++++++---- v3/pkg/application/webview_window_windows.go | 16 ++++++++++++-- 6 files changed, 68 insertions(+), 11 deletions(-) diff --git a/v3/examples/window/main.go b/v3/examples/window/main.go index bfa6d22522a..f427d44946a 100644 --- a/v3/examples/window/main.go +++ b/v3/examples/window/main.go @@ -445,11 +445,13 @@ func main() { }) }) - if runtime.GOOS == "windows" { - stateMenu.Add("Flash Start").OnClick(func(ctx *application.Context) { + if runtime.GOOS != "darwin" { + stateMenu.Add("Flash for 5s").OnClick(func(ctx *application.Context) { currentWindow(func(w *application.WebviewWindow) { time.Sleep(2 * time.Second) w.Flash(true) + time.Sleep(5 * time.Second) + w.Flash(false) }) }) } diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 5c664f395e4..02a9a33b8aa 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -1039,6 +1039,11 @@ func (w *linuxWebviewWindow) startDrag() error { return nil } +func (w *linuxWebviewWindow) flash(enabled bool) { + // Flash the window to get the user's attention + C.gtk_window_set_urgency_hint(w.gtkWindow(), gtkBool(enabled)) +} + func enableDevTools(webview pointer) { settings := C.webkit_web_view_get_settings((*C.WebKitWebView)(webview)) enabled := C.webkit_settings_get_enable_developer_extras(settings) diff --git a/v3/pkg/application/webview_window.go b/v3/pkg/application/webview_window.go index b08f39008f4..a8937505f19 100644 --- a/v3/pkg/application/webview_window.go +++ b/v3/pkg/application/webview_window.go @@ -64,6 +64,8 @@ type ( isVisible() bool isFocused() bool setFullscreenButtonEnabled(enabled bool) + setMinimiseButtonEnabled(enabled bool) + setMaximiseButtonEnabled(enabled bool) focus() show() hide() @@ -532,6 +534,26 @@ func (w *WebviewWindow) SetFullscreenButtonEnabled(enabled bool) Window { return w } +func (w *WebviewWindow) SetMinimiseButtonEnabled(enabled bool) Window { + w.options.FullscreenButtonEnabled = enabled + if w.impl != nil { + InvokeSync(func() { + w.impl.setMinimiseButtonEnabled(enabled) + }) + } + return w +} + +func (w *WebviewWindow) SetMaximiseButtonEnabled(enabled bool) Window { + w.options.FullscreenButtonEnabled = enabled + if w.impl != nil { + InvokeSync(func() { + w.impl.setMaximiseButtonEnabled(enabled) + }) + } + return w +} + // Flash flashes the window's taskbar button/icon. // Useful to indicate that attention is required. Windows only. func (w *WebviewWindow) Flash(enabled bool) { diff --git a/v3/pkg/application/webview_window_darwin.go b/v3/pkg/application/webview_window_darwin.go index b185e189fdc..86046f88807 100644 --- a/v3/pkg/application/webview_window_darwin.go +++ b/v3/pkg/application/webview_window_darwin.go @@ -1132,13 +1132,13 @@ func (w *macosWebviewWindow) run() { } if macOptions.DisableMinimiseButton { - C.enableMinimiseButton(w.nsWindow, C.bool(false)) + w.setMinimiseButtonEnabled(w.nsWindow, false) } if macOptions.DisableMaximiseButton { - C.enableMaximiseButton(w.nsWindow, C.bool(false)) + w.setMaximiseButtonEnabled(w.nsWindow, false) } if macOptions.DisableCloseButton { - C.enableCloseButton(w.nsWindow, C.bool(false)) + w.enableCloseButton(w.nsWindow, false) } if options.IgnoreMouseEvents { @@ -1269,3 +1269,15 @@ func (w *macosWebviewWindow) startDrag() error { C.startDrag(w.nsWindow) return nil } + +func (w *macosWebviewWindow) setMinimiseButtonEnabled(enabled bool) { + C.enableMinimiseButton(w.nsWindow, C.bool(enabled)) +} + +func (w *macosWebviewWindow) setMaximiseButtonEnabled(enabled bool) { + C.enableMaximiseButton(w.nsWindow, C.bool(enabled)) +} + +func (w *macosWebviewWindow) setCloseButtonEnabled(enabled bool) { + C.enableCloseButton(w.nsWindow, C.bool(enabled)) +} diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 1309fa7b86e..75168494ed0 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -36,6 +36,14 @@ type linuxWebviewWindow struct { gtkmenu pointer } +func (w *linuxWebviewWindow) setMinimiseButtonEnabled(enabled bool) { + // Not available in Linux +} + +func (w *linuxWebviewWindow) setMaximiseButtonEnabled(enabled bool) { + // Not available in Linux +} + var ( registered bool = false // avoid 'already registered message' about 'wails://' ) @@ -105,10 +113,6 @@ func (w *linuxWebviewWindow) unminimise() { w.present() } -func (w *linuxWebviewWindow) flash(enabled bool) { - // Not supported on linux -} - func (w *linuxWebviewWindow) on(eventID uint) { // TODO: Test register/unregister listener for linux events //C.registerListener(C.uint(eventID)) diff --git a/v3/pkg/application/webview_window_windows.go b/v3/pkg/application/webview_window_windows.go index 642feef28f9..5d2e164945c 100644 --- a/v3/pkg/application/webview_window_windows.go +++ b/v3/pkg/application/webview_window_windows.go @@ -238,8 +238,12 @@ func (w *windowsWebviewWindow) run() { w.setSize(options.Width, options.Height) // Min/max buttons - w.setStyle(!options.Windows.DisableMinimiseButton, w32.WS_MINIMIZEBOX) - w.setStyle(!options.Windows.DisableMaximiseButton, w32.WS_MAXIMIZEBOX) + if !options.Windows.DisableMinimiseButton { + w.setMinimiseButtonEnabled(false) + } + if !options.Windows.DisableMaximiseButton { + w.setMaximiseButtonEnabled(false) + } // Register the window with the application getNativeApplication().registerWindow(w) @@ -1626,6 +1630,14 @@ func (w *windowsWebviewWindow) processMessageWithAdditionalObjects(message strin } } +func (w *windowsWebviewWindow) setMaximiseButtonEnabled(enabled bool) { + w.setStyle(enabled, w32.WS_MINIMIZEBOX) +} + +func (w *windowsWebviewWindow) setMinimiseButtonEnabled(enabled bool) { + w.setStyle(enabled, w32.WS_MAXIMIZEBOX) +} + func ScaleWithDPI(pixels int, dpi uint) int { return (pixels * int(dpi)) / 96 } From 6b0daf3da9a6a0d503b4f3663e322e4fb96b5775 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 4 Feb 2024 12:42:00 +1100 Subject: [PATCH 059/369] Update windowSetupSignalHandlers & linux events --- v3/pkg/application/linux_cgo.go | 27 ++++++++++++++++++++++ v3/pkg/application/webview_window_linux.go | 3 ++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 02a9a33b8aa..179ad26ca8c 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -1005,6 +1005,33 @@ func handleLoadChanged(webview *C.WebKitWebView, event C.WebKitLoadEvent, data C } } +func windowSetupSignalHandlers(windowId uint, window, webview pointer, emit func(e events.WindowEventType)) { + + c := NewCalloc() + defer c.Free() + + winID := unsafe.Pointer(uintptr(C.uint(windowId))) + + // Set up the window close event + C.signal_connect(unsafe.Pointer(window), c.String("delete-event"), C.handleDeleteEvent, winID) + C.signal_connect(unsafe.Pointer(webview), c.String("load-changed"), C.handleLoadChanged, winID) + + contentManager := C.webkit_web_view_get_user_content_manager((*C.WebKitWebView)(webview)) + C.signal_connect(unsafe.Pointer(contentManager), c.String("script-message-received::external"), C.sendMessageToBackend, nil) + C.signal_connect(unsafe.Pointer(webview), c.String("button-press-event"), C.onButtonEvent, winID) + C.signal_connect(unsafe.Pointer(webview), c.String("button-release-event"), C.onButtonEvent, winID) + C.signal_connect(unsafe.Pointer(webview), c.String("key-press-event"), C.onKeyPressEvent, winID) + +} + +//export handleLoadChanged +func handleLoadChanged(webview *C.WebKitWebView, event C.WebKitLoadEvent, data C.uintptr_t) { + switch event { + case C.WEBKIT_LOAD_FINISHED: + processWindowEvent(C.uint(data), C.uint(events.Linux.WindowLoadChanged)) + } +} + func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventType)) { c := NewCalloc() diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 75168494ed0..e03471822c2 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -5,11 +5,12 @@ package application import "C" import ( "fmt" + "math" + "github.com/wailsapp/wails/v3/internal/assetserver" "github.com/wailsapp/wails/v3/internal/capabilities" "github.com/wailsapp/wails/v3/internal/runtime" "github.com/wailsapp/wails/v3/pkg/events" - "math" ) type dragInfo struct { From 84e1bb4d9bbb97933432ed342e9dc640f79b1878 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 4 Feb 2024 18:16:59 +1100 Subject: [PATCH 060/369] Improve Linux application events and refactor app method receivers This commit includes the addition of common events for the Linux platform. Refactored and standardized the method receivers for the application from 'm' to 'l'. Also, the application startup events in the window example have been updated according to the new naming scheme. --- v3/pkg/application/application_linux.go | 91 ++++++++++++---------- v3/pkg/application/dialogs_linux.go | 4 +- v3/pkg/application/events_common_linux.go | 4 +- v3/pkg/application/mainthread_linux.go | 2 +- v3/pkg/application/screen_linux.go | 6 +- v3/pkg/application/webview_window_linux.go | 10 +++ 6 files changed, 67 insertions(+), 50 deletions(-) diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index 99981bd3345..c9692945831 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -34,7 +34,7 @@ type linuxApp struct { theme string } -func (a *linuxApp) GetFlags(options Options) map[string]any { +func (l *linuxApp) GetFlags(options Options) map[string]any { if options.Flags == nil { options.Flags = make(map[string]any) } @@ -45,28 +45,31 @@ func getNativeApplication() *linuxApp { return globalApplication.impl.(*linuxApp) } -func (a *linuxApp) hide() { - a.hideAllWindows() +func (l *linuxApp) hide() { + hideAllWindows(l.application) } -func (a *linuxApp) show() { - a.showAllWindows() +func (l *linuxApp) show() { + showAllWindows(l.application) } -func (a *linuxApp) on(eventID uint) { - // TODO: Test register/unregister events - //C.registerApplicationEvent(l.application, C.uint(eventID)) +func (l *linuxApp) on(eventID uint) { + // TODO: What do we need to do here? + log.Println("linuxApp.on()", eventID) } -func (a *linuxApp) setIcon(icon []byte) { - +func (l *linuxApp) setIcon(icon []byte) { log.Println("linuxApp.setIcon", "not implemented") } -func (a *linuxApp) name() string { +func (l *linuxApp) name() string { return appName() } +func (l *linuxApp) getCurrentWindowID() uint { + return getCurrentWindowID(l.application, l.windows) +} + type rnr struct { f func() } @@ -75,7 +78,22 @@ func (r rnr) run() { r.f() } -func (a *linuxApp) setApplicationMenu(menu *Menu) { +func (l *linuxApp) getApplicationMenu() pointer { + if l.applicationMenu != nilPointer { + return l.applicationMenu + } + + menu := globalApplication.ApplicationMenu + if menu != nil { + InvokeSync(func() { + menu.Update() + }) + l.applicationMenu = (menu.impl).(*linuxMenu).native + } + return l.applicationMenu +} + +func (l *linuxApp) setApplicationMenu(menu *Menu) { // FIXME: How do we avoid putting a menu? if menu == nil { // Create a default menu @@ -84,55 +102,44 @@ func (a *linuxApp) setApplicationMenu(menu *Menu) { } } -func (a *linuxApp) run() error { +func (l *linuxApp) run() error { - a.parent.On(events.Linux.ApplicationStartup, func(evt *Event) { + l.parent.On(events.Linux.ApplicationStartup, func(evt *Event) { fmt.Println("events.Linux.ApplicationStartup received!") }) - a.setupCommonEvents() - a.monitorThemeChanges() - return appRun(a.application) -} - -func (a *linuxApp) unregisterWindow(w windowPointer) { - a.windowMapLock.Lock() - delete(a.windowMap, w) - a.windowMapLock.Unlock() - - // If this was the last window... - if len(a.windowMap) == 0 && !a.parent.options.Linux.DisableQuitOnLastWindowClosed { - a.destroy() - } + l.setupCommonEvents() + l.monitorThemeChanges() + return appRun(l.application) } -func (a *linuxApp) destroy() { +func (l *linuxApp) destroy() { if !globalApplication.shouldQuit() { return } globalApplication.cleanup() - appDestroy(a.application) + appDestroy(l.application) } -func (a *linuxApp) isOnMainThread() bool { +func (l *linuxApp) isOnMainThread() bool { return isOnMainThread() } // register our window to our parent mapping -func (a *linuxApp) registerWindow(window pointer, id uint) { - a.windowMapLock.Lock() - a.windowMap[windowPointer(window)] = id - a.windowMapLock.Unlock() +func (l *linuxApp) registerWindow(window pointer, id uint) { + l.windowsLock.Lock() + l.windows[windowPointer(window)] = id + l.windowsLock.Unlock() } -func (a *linuxApp) isDarkMode() bool { - return strings.Contains(a.theme, "dark") +func (l *linuxApp) isDarkMode() bool { + return strings.Contains(l.theme, "dark") } -func (a *linuxApp) monitorThemeChanges() { +func (l *linuxApp) monitorThemeChanges() { go func() { conn, err := dbus.ConnectSessionBus() if err != nil { - a.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err) + l.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err) return } defer conn.Close() @@ -165,10 +172,10 @@ func (a *linuxApp) monitorThemeChanges() { continue } - if theme != a.theme { - a.theme = theme + if theme != l.theme { + l.theme = theme event := newApplicationEvent(events.Common.ThemeChanged) - event.Context().setIsDarkMode(a.isDarkMode()) + event.Context().setIsDarkMode(l.isDarkMode()) applicationEvents <- event } diff --git a/v3/pkg/application/dialogs_linux.go b/v3/pkg/application/dialogs_linux.go index be480d17677..49499dda14e 100644 --- a/v3/pkg/application/dialogs_linux.go +++ b/v3/pkg/application/dialogs_linux.go @@ -1,7 +1,7 @@ package application -func (a *linuxApp) showAboutDialog(title string, message string, icon []byte) { - window := globalApplication.getWindowForID(a.getCurrentWindowID()) +func (l *linuxApp) showAboutDialog(title string, message string, icon []byte) { + window := globalApplication.getWindowForID(l.getCurrentWindowID()) var parent uintptr if window != nil { parent, _ = window.(*WebviewWindow).NativeWindowHandle() diff --git a/v3/pkg/application/events_common_linux.go b/v3/pkg/application/events_common_linux.go index e06fb8cfefc..530ac1563ab 100644 --- a/v3/pkg/application/events_common_linux.go +++ b/v3/pkg/application/events_common_linux.go @@ -9,11 +9,11 @@ var commonApplicationEventMap = map[events.ApplicationEventType]events.Applicati events.Linux.SystemThemeChanged: events.Common.ThemeChanged, } -func (a *linuxApp) setupCommonEvents() { +func (l *linuxApp) setupCommonEvents() { for sourceEvent, targetEvent := range commonApplicationEventMap { sourceEvent := sourceEvent targetEvent := targetEvent - a.parent.On(sourceEvent, func(event *Event) { + l.parent.On(sourceEvent, func(event *Event) { event.Id = uint(targetEvent) applicationEvents <- event }) diff --git a/v3/pkg/application/mainthread_linux.go b/v3/pkg/application/mainthread_linux.go index a718688bc4f..2a5ff3e2cb3 100644 --- a/v3/pkg/application/mainthread_linux.go +++ b/v3/pkg/application/mainthread_linux.go @@ -2,7 +2,7 @@ package application -func (a *linuxApp) dispatchOnMainThread(id uint) { +func (l *linuxApp) dispatchOnMainThread(id uint) { dispatchOnMainThread(id) } diff --git a/v3/pkg/application/screen_linux.go b/v3/pkg/application/screen_linux.go index d93cfbd927e..526752aceba 100644 --- a/v3/pkg/application/screen_linux.go +++ b/v3/pkg/application/screen_linux.go @@ -7,17 +7,17 @@ import ( "sync" ) -func (a *linuxApp) getPrimaryScreen() (*Screen, error) { +func (l *linuxApp) getPrimaryScreen() (*Screen, error) { return nil, fmt.Errorf("not implemented") } -func (a *linuxApp) getScreens() ([]*Screen, error) { +func (l *linuxApp) getScreens() ([]*Screen, error) { var wg sync.WaitGroup var screens []*Screen var err error wg.Add(1) InvokeSync(func() { - screens, err = getScreens(a.application) + screens, err = getScreens(l.application) wg.Done() }) wg.Wait() diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index e03471822c2..b9ba7d41471 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -161,6 +161,16 @@ func newWindowImpl(parent *WebviewWindow) *linuxWebviewWindow { return result } +func (w *linuxWebviewWindow) setTitle(title string) { + if !w.parent.options.Frameless { + windowSetTitle(w.window, title) + } +} + +func (w *linuxWebviewWindow) setSize(width, height int) { + windowResize(w.window, width, height) +} + func (w *linuxWebviewWindow) setMinMaxSize(minWidth, minHeight, maxWidth, maxHeight int) { if minWidth == 0 { minWidth = -1 From adae39efee08cd46f4ff079f4948c19c7ccaf29e Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 5 Feb 2024 21:37:35 +1100 Subject: [PATCH 061/369] Add webview GPU policy and update Linux options The commit introduces a set of webview GPU policies to control hardware acceleration. These policies define when hardware acceleration is enabled on the webview. An option for this has been added to the LinuxWindow struct for Linux specific windows. Additional code modification was carried out to use this new GPU policy option when calling `windowNew` function. Finally, the sequence of the GPU Policies in the const declaration has been updated for better readability. --- v3/pkg/application/webview_window_linux.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index b9ba7d41471..d990316d52e 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -237,7 +237,7 @@ func (w *linuxWebviewWindow) run() { w.gtkmenu = (menu.impl).(*linuxMenu).native } - w.window, w.webview, w.vbox = windowNew(app.application, w.gtkmenu, w.parent.id, w.parent.options.Linux.WebviewGpuPolicy) + w.window, w.webview, w.vbox = windowNew(app.application, menu, w.parent.id, w.parent.options.Linux.WebviewGpuPolicy) app.registerWindow(w.window, w.parent.id) // record our mapping w.connectSignals() if w.parent.options.EnableDragAndDrop { From 758c4c2c8d4289848ec8ef5053c82aa6c71c7fc8 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 6 Feb 2024 05:50:36 +1100 Subject: [PATCH 062/369] Refactor Linux application handling in webview This update introduces a LinuxOptions struct for Linux-specific application configurations and refines webview for Linux. The 'windows' map has been renamed to 'windowMap' to avoid confusion. Moreover, a method to unregister Windows has been added to ensure the Linux application automatically quits when the last window closes, unless explicitly disabled in the new LinuxOptions structure. Reset Window position after hiding. Some debug output has been removed. --- v3/pkg/application/application_linux.go | 19 ++++++++--- v3/pkg/application/webview_window_linux.go | 39 ++++++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index c9692945831..578bbbd50b7 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -67,7 +67,7 @@ func (l *linuxApp) name() string { } func (l *linuxApp) getCurrentWindowID() uint { - return getCurrentWindowID(l.application, l.windows) + return getCurrentWindowID(l.application, l.windowMap) } type rnr struct { @@ -112,6 +112,17 @@ func (l *linuxApp) run() error { return appRun(l.application) } +func (l *linuxApp) unregisterWindow(w windowPointer) { + l.windowMapLock.Lock() + delete(l.windowMap, w) + l.windowMapLock.Unlock() + + // If this was the last window... + if len(l.windowMap) == 0 && !l.parent.options.Linux.DisableQuitOnLastWindowClosed { + l.destroy() + } +} + func (l *linuxApp) destroy() { if !globalApplication.shouldQuit() { return @@ -126,9 +137,9 @@ func (l *linuxApp) isOnMainThread() bool { // register our window to our parent mapping func (l *linuxApp) registerWindow(window pointer, id uint) { - l.windowsLock.Lock() - l.windows[windowPointer(window)] = id - l.windowsLock.Unlock() + l.windowMapLock.Lock() + l.windowMap[windowPointer(window)] = id + l.windowMapLock.Unlock() } func (l *linuxApp) isDarkMode() bool { diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index d990316d52e..7845c760ea1 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -110,6 +110,24 @@ func (w *linuxWebviewWindow) disableSizeConstraints() { w.setMinMaxSize(x, y, width*scale, height*scale) } +func (w *linuxWebviewWindow) unfullscreen() { + windowUnfullscreen(w.window) + w.unmaximise() +} + +func (w *linuxWebviewWindow) fullscreen() { + w.maximise() + //w.lastWidth, w.lastHeight = w.size() + x, y, width, height, scale := windowGetCurrentMonitorGeometry(w.window) + if x == -1 && y == -1 && width == -1 && height == -1 { + return + } + w.setMinMaxSize(0, 0, width*scale, height*scale) + w.setSize(width*scale, height*scale) + windowFullscreen(w.window) + w.setRelativePosition(0, 0) +} + func (w *linuxWebviewWindow) unminimise() { w.present() } @@ -127,6 +145,27 @@ func (w *linuxWebviewWindow) windowZoom() { w.zoom() // FIXME> This should be removed } +func (w *linuxWebviewWindow) close() { + windowClose(w.window) + getNativeApplication().unregisterWindow(windowPointer(w.window)) +} + +func (w *linuxWebviewWindow) zoomIn() { + windowZoomIn(w.webview) +} + +func (w *linuxWebviewWindow) zoomOut() { + windowZoomOut(w.webview) +} + +func (w *linuxWebviewWindow) zoomReset() { + windowZoomSet(w.webview, 1.0) +} + +func (w *linuxWebviewWindow) reload() { + windowReload(w.webview, "wails://") +} + func (w *linuxWebviewWindow) forceReload() { w.reload() } From a048233f4c7812f770a092fccfeb19ae7592ffde Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 6 Feb 2024 21:14:51 +1100 Subject: [PATCH 063/369] Added menu cloning. Introduced the ability to clone a menu, along with its submenus, in Linux-based web applications to create a full deep copy. This fixes reusing the application menu for window menus. --- v3/pkg/application/application_linux.go | 19 ++----------------- v3/pkg/application/webview_window_linux.go | 10 +--------- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index 578bbbd50b7..b94f0812752 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -54,8 +54,8 @@ func (l *linuxApp) show() { } func (l *linuxApp) on(eventID uint) { - // TODO: What do we need to do here? - log.Println("linuxApp.on()", eventID) + // TODO: Test register/unregister events + //C.registerApplicationEvent(l.application, C.uint(eventID)) } func (l *linuxApp) setIcon(icon []byte) { @@ -78,21 +78,6 @@ func (r rnr) run() { r.f() } -func (l *linuxApp) getApplicationMenu() pointer { - if l.applicationMenu != nilPointer { - return l.applicationMenu - } - - menu := globalApplication.ApplicationMenu - if menu != nil { - InvokeSync(func() { - menu.Update() - }) - l.applicationMenu = (menu.impl).(*linuxMenu).native - } - return l.applicationMenu -} - func (l *linuxApp) setApplicationMenu(menu *Menu) { // FIXME: How do we avoid putting a menu? if menu == nil { diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 7845c760ea1..daad30ae680 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -37,14 +37,6 @@ type linuxWebviewWindow struct { gtkmenu pointer } -func (w *linuxWebviewWindow) setMinimiseButtonEnabled(enabled bool) { - // Not available in Linux -} - -func (w *linuxWebviewWindow) setMaximiseButtonEnabled(enabled bool) { - // Not available in Linux -} - var ( registered bool = false // avoid 'already registered message' about 'wails://' ) @@ -276,7 +268,7 @@ func (w *linuxWebviewWindow) run() { w.gtkmenu = (menu.impl).(*linuxMenu).native } - w.window, w.webview, w.vbox = windowNew(app.application, menu, w.parent.id, w.parent.options.Linux.WebviewGpuPolicy) + w.window, w.webview, w.vbox = windowNew(app.application, w.gtkmenu, w.parent.id, w.parent.options.Linux.WebviewGpuPolicy) app.registerWindow(w.window, w.parent.id) // record our mapping w.connectSignals() if w.parent.options.EnableDragAndDrop { From 02a1b540ce7e01aeed6420b9b5b7cab4c999e857 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 7 Feb 2024 22:19:33 +1100 Subject: [PATCH 064/369] [WIP] refactor CGO methods --- v3/pkg/application/application_linux.go | 72 ++++++++++------------ v3/pkg/application/dialogs_linux.go | 4 +- v3/pkg/application/events_common_linux.go | 4 +- v3/pkg/application/linux_cgo.go | 12 ++-- v3/pkg/application/mainthread_linux.go | 2 +- v3/pkg/application/screen_linux.go | 6 +- v3/pkg/application/webview_window_linux.go | 54 +++++----------- 7 files changed, 65 insertions(+), 89 deletions(-) diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index b94f0812752..3029b96fb97 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -34,7 +34,7 @@ type linuxApp struct { theme string } -func (l *linuxApp) GetFlags(options Options) map[string]any { +func (a *linuxApp) GetFlags(options Options) map[string]any { if options.Flags == nil { options.Flags = make(map[string]any) } @@ -45,31 +45,27 @@ func getNativeApplication() *linuxApp { return globalApplication.impl.(*linuxApp) } -func (l *linuxApp) hide() { - hideAllWindows(l.application) +func (a *linuxApp) hide() { + a.hideAllWindows() } -func (l *linuxApp) show() { - showAllWindows(l.application) +func (a *linuxApp) show() { + a.showAllWindows() } -func (l *linuxApp) on(eventID uint) { +func (a *linuxApp) on(eventID uint) { // TODO: Test register/unregister events //C.registerApplicationEvent(l.application, C.uint(eventID)) } -func (l *linuxApp) setIcon(icon []byte) { +func (a *linuxApp) setIcon(icon []byte) { log.Println("linuxApp.setIcon", "not implemented") } -func (l *linuxApp) name() string { +func (a *linuxApp) name() string { return appName() } -func (l *linuxApp) getCurrentWindowID() uint { - return getCurrentWindowID(l.application, l.windowMap) -} - type rnr struct { f func() } @@ -78,7 +74,7 @@ func (r rnr) run() { r.f() } -func (l *linuxApp) setApplicationMenu(menu *Menu) { +func (a *linuxApp) setApplicationMenu(menu *Menu) { // FIXME: How do we avoid putting a menu? if menu == nil { // Create a default menu @@ -87,55 +83,55 @@ func (l *linuxApp) setApplicationMenu(menu *Menu) { } } -func (l *linuxApp) run() error { +func (a *linuxApp) run() error { - l.parent.On(events.Linux.ApplicationStartup, func(evt *Event) { + a.parent.On(events.Linux.ApplicationStartup, func(evt *Event) { fmt.Println("events.Linux.ApplicationStartup received!") }) - l.setupCommonEvents() - l.monitorThemeChanges() - return appRun(l.application) + a.setupCommonEvents() + a.monitorThemeChanges() + return appRun(a.application) } -func (l *linuxApp) unregisterWindow(w windowPointer) { - l.windowMapLock.Lock() - delete(l.windowMap, w) - l.windowMapLock.Unlock() +func (a *linuxApp) unregisterWindow(w windowPointer) { + a.windowMapLock.Lock() + delete(a.windowMap, w) + a.windowMapLock.Unlock() // If this was the last window... - if len(l.windowMap) == 0 && !l.parent.options.Linux.DisableQuitOnLastWindowClosed { - l.destroy() + if len(a.windowMap) == 0 && !a.parent.options.Linux.DisableQuitOnLastWindowClosed { + a.destroy() } } -func (l *linuxApp) destroy() { +func (a *linuxApp) destroy() { if !globalApplication.shouldQuit() { return } globalApplication.cleanup() - appDestroy(l.application) + appDestroy(a.application) } -func (l *linuxApp) isOnMainThread() bool { +func (a *linuxApp) isOnMainThread() bool { return isOnMainThread() } // register our window to our parent mapping -func (l *linuxApp) registerWindow(window pointer, id uint) { - l.windowMapLock.Lock() - l.windowMap[windowPointer(window)] = id - l.windowMapLock.Unlock() +func (a *linuxApp) registerWindow(window pointer, id uint) { + a.windowMapLock.Lock() + a.windowMap[windowPointer(window)] = id + a.windowMapLock.Unlock() } -func (l *linuxApp) isDarkMode() bool { - return strings.Contains(l.theme, "dark") +func (a *linuxApp) isDarkMode() bool { + return strings.Contains(a.theme, "dark") } -func (l *linuxApp) monitorThemeChanges() { +func (a *linuxApp) monitorThemeChanges() { go func() { conn, err := dbus.ConnectSessionBus() if err != nil { - l.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err) + a.parent.info("[WARNING] Failed to connect to session bus; monitoring for theme changes will not function:", err) return } defer conn.Close() @@ -168,10 +164,10 @@ func (l *linuxApp) monitorThemeChanges() { continue } - if theme != l.theme { - l.theme = theme + if theme != a.theme { + a.theme = theme event := newApplicationEvent(events.Common.ThemeChanged) - event.Context().setIsDarkMode(l.isDarkMode()) + event.Context().setIsDarkMode(a.isDarkMode()) applicationEvents <- event } diff --git a/v3/pkg/application/dialogs_linux.go b/v3/pkg/application/dialogs_linux.go index 49499dda14e..be480d17677 100644 --- a/v3/pkg/application/dialogs_linux.go +++ b/v3/pkg/application/dialogs_linux.go @@ -1,7 +1,7 @@ package application -func (l *linuxApp) showAboutDialog(title string, message string, icon []byte) { - window := globalApplication.getWindowForID(l.getCurrentWindowID()) +func (a *linuxApp) showAboutDialog(title string, message string, icon []byte) { + window := globalApplication.getWindowForID(a.getCurrentWindowID()) var parent uintptr if window != nil { parent, _ = window.(*WebviewWindow).NativeWindowHandle() diff --git a/v3/pkg/application/events_common_linux.go b/v3/pkg/application/events_common_linux.go index 530ac1563ab..e06fb8cfefc 100644 --- a/v3/pkg/application/events_common_linux.go +++ b/v3/pkg/application/events_common_linux.go @@ -9,11 +9,11 @@ var commonApplicationEventMap = map[events.ApplicationEventType]events.Applicati events.Linux.SystemThemeChanged: events.Common.ThemeChanged, } -func (l *linuxApp) setupCommonEvents() { +func (a *linuxApp) setupCommonEvents() { for sourceEvent, targetEvent := range commonApplicationEventMap { sourceEvent := sourceEvent targetEvent := targetEvent - l.parent.On(sourceEvent, func(event *Event) { + a.parent.On(sourceEvent, func(event *Event) { event.Id = uint(targetEvent) applicationEvents <- event }) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 179ad26ca8c..a06da016a94 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -1005,23 +1005,23 @@ func handleLoadChanged(webview *C.WebKitWebView, event C.WebKitLoadEvent, data C } } -func windowSetupSignalHandlers(windowId uint, window, webview pointer, emit func(e events.WindowEventType)) { +func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventType)) { c := NewCalloc() defer c.Free() - winID := unsafe.Pointer(uintptr(C.uint(windowId))) + winID := unsafe.Pointer(uintptr(C.uint(w.parent.ID()))) // Set up the window close event - C.signal_connect(unsafe.Pointer(window), c.String("delete-event"), C.handleDeleteEvent, winID) - C.signal_connect(unsafe.Pointer(webview), c.String("load-changed"), C.handleLoadChanged, winID) + wv := unsafe.Pointer(w.webview) + C.signal_connect(unsafe.Pointer(w.window), c.String("delete-event"), C.handleDeleteEvent, winID) + C.signal_connect(wv, c.String("load-changed"), C.handleLoadChanged, winID) - contentManager := C.webkit_web_view_get_user_content_manager((*C.WebKitWebView)(webview)) + contentManager := C.webkit_web_view_get_user_content_manager(w.webKitWebView()) C.signal_connect(unsafe.Pointer(contentManager), c.String("script-message-received::external"), C.sendMessageToBackend, nil) C.signal_connect(unsafe.Pointer(webview), c.String("button-press-event"), C.onButtonEvent, winID) C.signal_connect(unsafe.Pointer(webview), c.String("button-release-event"), C.onButtonEvent, winID) C.signal_connect(unsafe.Pointer(webview), c.String("key-press-event"), C.onKeyPressEvent, winID) - } //export handleLoadChanged diff --git a/v3/pkg/application/mainthread_linux.go b/v3/pkg/application/mainthread_linux.go index 2a5ff3e2cb3..a718688bc4f 100644 --- a/v3/pkg/application/mainthread_linux.go +++ b/v3/pkg/application/mainthread_linux.go @@ -2,7 +2,7 @@ package application -func (l *linuxApp) dispatchOnMainThread(id uint) { +func (a *linuxApp) dispatchOnMainThread(id uint) { dispatchOnMainThread(id) } diff --git a/v3/pkg/application/screen_linux.go b/v3/pkg/application/screen_linux.go index 526752aceba..d93cfbd927e 100644 --- a/v3/pkg/application/screen_linux.go +++ b/v3/pkg/application/screen_linux.go @@ -7,17 +7,17 @@ import ( "sync" ) -func (l *linuxApp) getPrimaryScreen() (*Screen, error) { +func (a *linuxApp) getPrimaryScreen() (*Screen, error) { return nil, fmt.Errorf("not implemented") } -func (l *linuxApp) getScreens() ([]*Screen, error) { +func (a *linuxApp) getScreens() ([]*Screen, error) { var wg sync.WaitGroup var screens []*Screen var err error wg.Add(1) InvokeSync(func() { - screens, err = getScreens(l.application) + screens, err = getScreens(a.application) wg.Done() }) wg.Wait() diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index daad30ae680..20cb8a7b231 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -7,6 +7,8 @@ import ( "fmt" "math" + "math" + "github.com/wailsapp/wails/v3/internal/assetserver" "github.com/wailsapp/wails/v3/internal/capabilities" "github.com/wailsapp/wails/v3/internal/runtime" @@ -102,15 +104,10 @@ func (w *linuxWebviewWindow) disableSizeConstraints() { w.setMinMaxSize(x, y, width*scale, height*scale) } -func (w *linuxWebviewWindow) unfullscreen() { - windowUnfullscreen(w.window) - w.unmaximise() -} - func (w *linuxWebviewWindow) fullscreen() { w.maximise() //w.lastWidth, w.lastHeight = w.size() - x, y, width, height, scale := windowGetCurrentMonitorGeometry(w.window) + x, y, width, height, scale := w.getCurrentMonitorGeometry() if x == -1 && y == -1 && width == -1 && height == -1 { return } @@ -137,27 +134,6 @@ func (w *linuxWebviewWindow) windowZoom() { w.zoom() // FIXME> This should be removed } -func (w *linuxWebviewWindow) close() { - windowClose(w.window) - getNativeApplication().unregisterWindow(windowPointer(w.window)) -} - -func (w *linuxWebviewWindow) zoomIn() { - windowZoomIn(w.webview) -} - -func (w *linuxWebviewWindow) zoomOut() { - windowZoomOut(w.webview) -} - -func (w *linuxWebviewWindow) zoomReset() { - windowZoomSet(w.webview, 1.0) -} - -func (w *linuxWebviewWindow) reload() { - windowReload(w.webview, "wails://") -} - func (w *linuxWebviewWindow) forceReload() { w.reload() } @@ -192,16 +168,6 @@ func newWindowImpl(parent *WebviewWindow) *linuxWebviewWindow { return result } -func (w *linuxWebviewWindow) setTitle(title string) { - if !w.parent.options.Frameless { - windowSetTitle(w.window, title) - } -} - -func (w *linuxWebviewWindow) setSize(width, height int) { - windowResize(w.window, width, height) -} - func (w *linuxWebviewWindow) setMinMaxSize(minWidth, minHeight, maxWidth, maxHeight int) { if minWidth == 0 { minWidth = -1 @@ -357,6 +323,20 @@ func (w *linuxWebviewWindow) run() { } } +func (w *linuxWebviewWindow) destroy() { + w.parent.markAsDestroyed() + // Free menu + if w.gtkmenu != nil { + menuDestroy(w.gtkmenu) + w.gtkmenu = nil + } + windowDestroy(w.window) +} + +func (w *linuxWebviewWindow) setEnabled(enabled bool) { + widgetSetSensitive(w.window, enabled) +} + func (w *linuxWebviewWindow) startResize(border string) error { // FIXME: what do we need to do here? return nil From 29363fc07f96ce6c0b17c4bd888ddb57a53b193f Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 9 Feb 2024 20:06:38 +1100 Subject: [PATCH 065/369] ToggleDevTools -> OpenDevTools More refactor CGO methods. --- v3/pkg/application/linux_cgo.go | 5 ---- v3/pkg/application/webview_window_linux.go | 27 ---------------------- 2 files changed, 32 deletions(-) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index a06da016a94..a42a7997d70 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -1066,11 +1066,6 @@ func (w *linuxWebviewWindow) startDrag() error { return nil } -func (w *linuxWebviewWindow) flash(enabled bool) { - // Flash the window to get the user's attention - C.gtk_window_set_urgency_hint(w.gtkWindow(), gtkBool(enabled)) -} - func enableDevTools(webview pointer) { settings := C.webkit_web_view_get_settings((*C.WebKitWebView)(webview)) enabled := C.webkit_settings_get_enable_developer_extras(settings) diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 20cb8a7b231..8a4a4d09a17 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -104,19 +104,6 @@ func (w *linuxWebviewWindow) disableSizeConstraints() { w.setMinMaxSize(x, y, width*scale, height*scale) } -func (w *linuxWebviewWindow) fullscreen() { - w.maximise() - //w.lastWidth, w.lastHeight = w.size() - x, y, width, height, scale := w.getCurrentMonitorGeometry() - if x == -1 && y == -1 && width == -1 && height == -1 { - return - } - w.setMinMaxSize(0, 0, width*scale, height*scale) - w.setSize(width*scale, height*scale) - windowFullscreen(w.window) - w.setRelativePosition(0, 0) -} - func (w *linuxWebviewWindow) unminimise() { w.present() } @@ -323,20 +310,6 @@ func (w *linuxWebviewWindow) run() { } } -func (w *linuxWebviewWindow) destroy() { - w.parent.markAsDestroyed() - // Free menu - if w.gtkmenu != nil { - menuDestroy(w.gtkmenu) - w.gtkmenu = nil - } - windowDestroy(w.window) -} - -func (w *linuxWebviewWindow) setEnabled(enabled bool) { - widgetSetSensitive(w.window, enabled) -} - func (w *linuxWebviewWindow) startResize(border string) error { // FIXME: what do we need to do here? return nil From 288a4757f8e8b2a6a794c0a68bb717279c8f01d3 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 10 Feb 2024 08:57:06 +1100 Subject: [PATCH 066/369] WindowID now correctly passed with webview request. --- v3/examples/events/assets/runtime.js | 1 + v3/examples/wml/assets/runtime.debug.js | 963 ------------------------ v3/pkg/application/linux_cgo.go | 58 +- 3 files changed, 32 insertions(+), 990 deletions(-) create mode 100644 v3/examples/events/assets/runtime.js delete mode 100644 v3/examples/wml/assets/runtime.debug.js diff --git a/v3/examples/events/assets/runtime.js b/v3/examples/events/assets/runtime.js new file mode 100644 index 00000000000..ec430090db6 --- /dev/null +++ b/v3/examples/events/assets/runtime.js @@ -0,0 +1 @@ +(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>Me,Text:()=>xe});var q=l(d.Clipboard,""),Ce=0,Se=1;function Me(e){return q(Ce,{text:e})}function xe(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var M=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",M=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(M=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){M=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return M&&i>0?(h("drag"),!1):M}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,Mi=21,xi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(Mi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(xi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>x,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},x=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,Mn=5,xn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),xn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(Mn,e);function oe(e,i=null){let n=new x(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/examples/wml/assets/runtime.debug.js b/v3/examples/wml/assets/runtime.debug.js deleted file mode 100644 index 101f237755c..00000000000 --- a/v3/examples/wml/assets/runtime.debug.js +++ /dev/null @@ -1,963 +0,0 @@ -(() => { - var __defProp = Object.defineProperty; - var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); - }; - - // desktop/@wailsio/runtime/src/log.js - function debugLog(message) { - console.log( - "%c wails3 %c " + message + " ", - "background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem", - "background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem" - ); - } - - // desktop/@wailsio/runtime/src/application.js - var application_exports = {}; - __export(application_exports, { - Hide: () => Hide, - Quit: () => Quit, - Show: () => Show - }); - - // node_modules/nanoid/non-secure/index.js - var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"; - var nanoid = (size2 = 21) => { - let id = ""; - let i = size2; - while (i--) { - id += urlAlphabet[Math.random() * 64 | 0]; - } - return id; - }; - - // desktop/@wailsio/runtime/src/runtime.js - var runtimeURL = window.location.origin + "/wails/runtime"; - var objectNames = { - Call: 0, - Clipboard: 1, - Application: 2, - Events: 3, - ContextMenu: 4, - Dialog: 5, - Window: 6, - Screens: 7, - System: 8, - Browser: 9 - }; - var clientId = nanoid(); - function newRuntimeCallerWithID(object, windowName) { - return function(method, args = null) { - return runtimeCallWithID(object, method, windowName, args); - }; - } - function runtimeCallWithID(objectID, method, windowName, args) { - let url = new URL(runtimeURL); - url.searchParams.append("object", objectID); - url.searchParams.append("method", method); - let fetchOptions = { - headers: {} - }; - if (windowName) { - fetchOptions.headers["x-wails-window-name"] = windowName; - } - if (args) { - url.searchParams.append("args", JSON.stringify(args)); - } - fetchOptions.headers["x-wails-client-id"] = clientId; - return new Promise((resolve, reject) => { - fetch(url, fetchOptions).then((response) => { - if (response.ok) { - if (response.headers.get("Content-Type") && response.headers.get("Content-Type").indexOf("application/json") !== -1) { - return response.json(); - } else { - return response.text(); - } - } - reject(Error(response.statusText)); - }).then((data) => resolve(data)).catch((error) => reject(error)); - }); - } - - // desktop/@wailsio/runtime/src/application.js - var call = newRuntimeCallerWithID(objectNames.Application, ""); - var HideMethod = 0; - var ShowMethod = 1; - var QuitMethod = 2; - function Hide() { - return call(HideMethod); - } - function Show() { - return call(ShowMethod); - } - function Quit() { - return call(QuitMethod); - } - - // desktop/@wailsio/runtime/src/browser.js - var browser_exports = {}; - __export(browser_exports, { - OpenURL: () => OpenURL - }); - var call2 = newRuntimeCallerWithID(objectNames.Browser, ""); - var BrowserOpenURL = 0; - function OpenURL(url) { - return call2(BrowserOpenURL, { url }); - } - - // desktop/@wailsio/runtime/src/clipboard.js - var clipboard_exports = {}; - __export(clipboard_exports, { - SetText: () => SetText, - Text: () => Text - }); - var call3 = newRuntimeCallerWithID(objectNames.Clipboard, ""); - var ClipboardSetText = 0; - var ClipboardText = 1; - function SetText(text) { - return call3(ClipboardSetText, { text }); - } - function Text() { - return call3(ClipboardText); - } - - // desktop/@wailsio/runtime/src/flags.js - var flags_exports = {}; - __export(flags_exports, { - GetFlag: () => GetFlag - }); - function GetFlag(keyString) { - try { - return window._wails.flags[keyString]; - } catch (e) { - throw new Error("Unable to retrieve flag '" + keyString + "': " + e); - } - } - - // desktop/@wailsio/runtime/src/screens.js - var screens_exports = {}; - __export(screens_exports, { - GetAll: () => GetAll, - GetCurrent: () => GetCurrent, - GetPrimary: () => GetPrimary - }); - var call4 = newRuntimeCallerWithID(objectNames.Screens, ""); - var getAll = 0; - var getPrimary = 1; - var getCurrent = 2; - function GetAll() { - return call4(getAll); - } - function GetPrimary() { - return call4(getPrimary); - } - function GetCurrent() { - return call4(getCurrent); - } - - // desktop/@wailsio/runtime/src/system.js - var system_exports = {}; - __export(system_exports, { - Capabilities: () => Capabilities, - Environment: () => Environment, - IsAMD64: () => IsAMD64, - IsARM: () => IsARM, - IsARM64: () => IsARM64, - IsDarkMode: () => IsDarkMode, - IsDebug: () => IsDebug, - IsLinux: () => IsLinux, - IsMac: () => IsMac, - IsWindows: () => IsWindows, - invoke: () => invoke - }); - var call5 = newRuntimeCallerWithID(objectNames.System, ""); - var systemIsDarkMode = 0; - var environment = 1; - function invoke(msg) { - if (window.chrome) { - return window.chrome.webview.postMessage(msg); - } - return window.webkit.messageHandlers.external.postMessage; - } - function IsDarkMode() { - return call5(systemIsDarkMode); - } - function Capabilities() { - let response = fetch("/wails/capabilities"); - return response.json(); - } - function Environment() { - return call5(environment); - } - function IsWindows() { - return window._wails.environment.OS === "windows"; - } - function IsLinux() { - return window._wails.environment.OS === "linux"; - } - function IsMac() { - return window._wails.environment.OS === "darwin"; - } - function IsAMD64() { - return window._wails.environment.Arch === "amd64"; - } - function IsARM() { - return window._wails.environment.Arch === "arm"; - } - function IsARM64() { - return window._wails.environment.Arch === "arm64"; - } - function IsDebug() { - return window._wails.environment.Debug === true; - } - - // desktop/@wailsio/runtime/src/window.js - var window_exports = {}; - __export(window_exports, { - Center: () => Center, - Close: () => Close, - Fullscreen: () => Fullscreen, - Get: () => Get, - GetZoomLevel: () => GetZoomLevel, - Height: () => Height, - Hide: () => Hide2, - Maximise: () => Maximise, - Minimise: () => Minimise, - RelativePosition: () => RelativePosition, - Restore: () => Restore, - Screen: () => Screen, - SetAlwaysOnTop: () => SetAlwaysOnTop, - SetBackgroundColour: () => SetBackgroundColour, - SetMaxSize: () => SetMaxSize, - SetMinSize: () => SetMinSize, - SetRelativePosition: () => SetRelativePosition, - SetResizable: () => SetResizable, - SetSize: () => SetSize, - SetTitle: () => SetTitle, - SetZoomLevel: () => SetZoomLevel, - Show: () => Show2, - Size: () => Size, - ToggleMaximise: () => ToggleMaximise, - UnMaximise: () => UnMaximise, - UnMinimise: () => UnMinimise, - Width: () => Width, - ZoomIn: () => ZoomIn, - ZoomOut: () => ZoomOut, - ZoomReset: () => ZoomReset - }); - var center = 0; - var setTitle = 1; - var fullscreen = 2; - var unFullscreen = 3; - var setSize = 4; - var size = 5; - var setMaxSize = 6; - var setMinSize = 7; - var setAlwaysOnTop = 8; - var setRelativePosition = 9; - var relativePosition = 10; - var screen = 11; - var hide = 12; - var maximise = 13; - var unMaximise = 14; - var toggleMaximise = 15; - var minimise = 16; - var unMinimise = 17; - var restore = 18; - var show = 19; - var close = 20; - var setBackgroundColour = 21; - var setResizable = 22; - var width = 23; - var height = 24; - var zoomIn = 25; - var zoomOut = 26; - var zoomReset = 27; - var getZoomLevel = 28; - var setZoomLevel = 29; - var thisWindow = Get(""); - function createWindow(call9) { - return { - Get: (windowName) => createWindow(newRuntimeCallerWithID(objectNames.Window, windowName)), - Center: () => call9(center), - SetTitle: (title) => call9(setTitle, { title }), - Fullscreen: () => call9(fullscreen), - UnFullscreen: () => call9(unFullscreen), - SetSize: (width2, height2) => call9(setSize, { width: width2, height: height2 }), - Size: () => call9(size), - SetMaxSize: (width2, height2) => call9(setMaxSize, { width: width2, height: height2 }), - SetMinSize: (width2, height2) => call9(setMinSize, { width: width2, height: height2 }), - SetAlwaysOnTop: (onTop) => call9(setAlwaysOnTop, { alwaysOnTop: onTop }), - SetRelativePosition: (x, y) => call9(setRelativePosition, { x, y }), - RelativePosition: () => call9(relativePosition), - Screen: () => call9(screen), - Hide: () => call9(hide), - Maximise: () => call9(maximise), - UnMaximise: () => call9(unMaximise), - ToggleMaximise: () => call9(toggleMaximise), - Minimise: () => call9(minimise), - UnMinimise: () => call9(unMinimise), - Restore: () => call9(restore), - Show: () => call9(show), - Close: () => call9(close), - SetBackgroundColour: (r, g, b, a) => call9(setBackgroundColour, { r, g, b, a }), - SetResizable: (resizable) => call9(setResizable, { resizable }), - Width: () => call9(width), - Height: () => call9(height), - ZoomIn: () => call9(zoomIn), - ZoomOut: () => call9(zoomOut), - ZoomReset: () => call9(zoomReset), - GetZoomLevel: () => call9(getZoomLevel), - SetZoomLevel: (zoomLevel) => call9(setZoomLevel, { zoomLevel }) - }; - } - function Get(windowName) { - return createWindow(newRuntimeCallerWithID(objectNames.Window, windowName)); - } - function Center() { - thisWindow.Center(); - } - function SetTitle(title) { - thisWindow.SetTitle(title); - } - function Fullscreen() { - thisWindow.Fullscreen(); - } - function SetSize(width2, height2) { - thisWindow.SetSize(width2, height2); - } - function Size() { - return thisWindow.Size(); - } - function SetMaxSize(width2, height2) { - thisWindow.SetMaxSize(width2, height2); - } - function SetMinSize(width2, height2) { - thisWindow.SetMinSize(width2, height2); - } - function SetAlwaysOnTop(onTop) { - thisWindow.SetAlwaysOnTop(onTop); - } - function SetRelativePosition(x, y) { - thisWindow.SetRelativePosition(x, y); - } - function RelativePosition() { - return thisWindow.RelativePosition(); - } - function Screen() { - return thisWindow.Screen(); - } - function Hide2() { - thisWindow.Hide(); - } - function Maximise() { - thisWindow.Maximise(); - } - function UnMaximise() { - thisWindow.UnMaximise(); - } - function ToggleMaximise() { - thisWindow.ToggleMaximise(); - } - function Minimise() { - thisWindow.Minimise(); - } - function UnMinimise() { - thisWindow.UnMinimise(); - } - function Restore() { - thisWindow.Restore(); - } - function Show2() { - thisWindow.Show(); - } - function Close() { - thisWindow.Close(); - } - function SetBackgroundColour(r, g, b, a) { - thisWindow.SetBackgroundColour(r, g, b, a); - } - function SetResizable(resizable) { - thisWindow.SetResizable(resizable); - } - function Width() { - return thisWindow.Width(); - } - function Height() { - return thisWindow.Height(); - } - function ZoomIn() { - thisWindow.ZoomIn(); - } - function ZoomOut() { - thisWindow.ZoomOut(); - } - function ZoomReset() { - thisWindow.ZoomReset(); - } - function GetZoomLevel() { - return thisWindow.GetZoomLevel(); - } - function SetZoomLevel(zoomLevel) { - thisWindow.SetZoomLevel(zoomLevel); - } - - // desktop/@wailsio/runtime/src/wml.js - var wml_exports = {}; - __export(wml_exports, { - Reload: () => Reload - }); - - // desktop/@wailsio/runtime/src/events.js - var events_exports = {}; - __export(events_exports, { - Emit: () => Emit, - Off: () => Off, - OffAll: () => OffAll, - On: () => On, - OnMultiple: () => OnMultiple, - Once: () => Once, - Types: () => Types, - WailsEvent: () => WailsEvent, - setup: () => setup - }); - - // desktop/@wailsio/runtime/src/event_types.js - var EventTypes = { - Windows: { - SystemThemeChanged: "windows:SystemThemeChanged", - APMPowerStatusChange: "windows:APMPowerStatusChange", - APMSuspend: "windows:APMSuspend", - APMResumeAutomatic: "windows:APMResumeAutomatic", - APMResumeSuspend: "windows:APMResumeSuspend", - APMPowerSettingChange: "windows:APMPowerSettingChange", - ApplicationStarted: "windows:ApplicationStarted", - WebViewNavigationCompleted: "windows:WebViewNavigationCompleted", - WindowInactive: "windows:WindowInactive", - WindowActive: "windows:WindowActive", - WindowClickActive: "windows:WindowClickActive", - WindowMaximise: "windows:WindowMaximise", - WindowUnMaximise: "windows:WindowUnMaximise", - WindowFullscreen: "windows:WindowFullscreen", - WindowUnFullscreen: "windows:WindowUnFullscreen", - WindowRestore: "windows:WindowRestore", - WindowMinimise: "windows:WindowMinimise", - WindowUnMinimise: "windows:WindowUnMinimise", - WindowClose: "windows:WindowClose", - WindowSetFocus: "windows:WindowSetFocus", - WindowKillFocus: "windows:WindowKillFocus", - WindowDragDrop: "windows:WindowDragDrop", - WindowDragEnter: "windows:WindowDragEnter", - WindowDragLeave: "windows:WindowDragLeave", - WindowDragOver: "windows:WindowDragOver" - }, - Mac: { - ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive", - ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties", - ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance", - ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon", - ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState", - ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters", - ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame", - ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation", - ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", - ApplicationDidHide: "mac:ApplicationDidHide", - ApplicationDidResignActiveNotification: "mac:ApplicationDidResignActiveNotification", - ApplicationDidUnhide: "mac:ApplicationDidUnhide", - ApplicationDidUpdate: "mac:ApplicationDidUpdate", - ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive", - ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching", - ApplicationWillHide: "mac:ApplicationWillHide", - ApplicationWillResignActive: "mac:ApplicationWillResignActive", - ApplicationWillTerminate: "mac:ApplicationWillTerminate", - ApplicationWillUnhide: "mac:ApplicationWillUnhide", - ApplicationWillUpdate: "mac:ApplicationWillUpdate", - ApplicationDidChangeTheme: "mac:ApplicationDidChangeTheme!", - ApplicationShouldHandleReopen: "mac:ApplicationShouldHandleReopen!", - WindowDidBecomeKey: "mac:WindowDidBecomeKey", - WindowDidBecomeMain: "mac:WindowDidBecomeMain", - WindowDidBeginSheet: "mac:WindowDidBeginSheet", - WindowDidChangeAlpha: "mac:WindowDidChangeAlpha", - WindowDidChangeBackingLocation: "mac:WindowDidChangeBackingLocation", - WindowDidChangeBackingProperties: "mac:WindowDidChangeBackingProperties", - WindowDidChangeCollectionBehavior: "mac:WindowDidChangeCollectionBehavior", - WindowDidChangeEffectiveAppearance: "mac:WindowDidChangeEffectiveAppearance", - WindowDidChangeOcclusionState: "mac:WindowDidChangeOcclusionState", - WindowDidChangeOrderingMode: "mac:WindowDidChangeOrderingMode", - WindowDidChangeScreen: "mac:WindowDidChangeScreen", - WindowDidChangeScreenParameters: "mac:WindowDidChangeScreenParameters", - WindowDidChangeScreenProfile: "mac:WindowDidChangeScreenProfile", - WindowDidChangeScreenSpace: "mac:WindowDidChangeScreenSpace", - WindowDidChangeScreenSpaceProperties: "mac:WindowDidChangeScreenSpaceProperties", - WindowDidChangeSharingType: "mac:WindowDidChangeSharingType", - WindowDidChangeSpace: "mac:WindowDidChangeSpace", - WindowDidChangeSpaceOrderingMode: "mac:WindowDidChangeSpaceOrderingMode", - WindowDidChangeTitle: "mac:WindowDidChangeTitle", - WindowDidChangeToolbar: "mac:WindowDidChangeToolbar", - WindowDidChangeVisibility: "mac:WindowDidChangeVisibility", - WindowDidDeminiaturize: "mac:WindowDidDeminiaturize", - WindowDidEndSheet: "mac:WindowDidEndSheet", - WindowDidEnterFullScreen: "mac:WindowDidEnterFullScreen", - WindowDidEnterVersionBrowser: "mac:WindowDidEnterVersionBrowser", - WindowDidExitFullScreen: "mac:WindowDidExitFullScreen", - WindowDidExitVersionBrowser: "mac:WindowDidExitVersionBrowser", - WindowDidExpose: "mac:WindowDidExpose", - WindowDidFocus: "mac:WindowDidFocus", - WindowDidMiniaturize: "mac:WindowDidMiniaturize", - WindowDidMove: "mac:WindowDidMove", - WindowDidOrderOffScreen: "mac:WindowDidOrderOffScreen", - WindowDidOrderOnScreen: "mac:WindowDidOrderOnScreen", - WindowDidResignKey: "mac:WindowDidResignKey", - WindowDidResignMain: "mac:WindowDidResignMain", - WindowDidResize: "mac:WindowDidResize", - WindowDidUpdate: "mac:WindowDidUpdate", - WindowDidUpdateAlpha: "mac:WindowDidUpdateAlpha", - WindowDidUpdateCollectionBehavior: "mac:WindowDidUpdateCollectionBehavior", - WindowDidUpdateCollectionProperties: "mac:WindowDidUpdateCollectionProperties", - WindowDidUpdateShadow: "mac:WindowDidUpdateShadow", - WindowDidUpdateTitle: "mac:WindowDidUpdateTitle", - WindowDidUpdateToolbar: "mac:WindowDidUpdateToolbar", - WindowDidUpdateVisibility: "mac:WindowDidUpdateVisibility", - WindowShouldClose: "mac:WindowShouldClose!", - WindowWillBecomeKey: "mac:WindowWillBecomeKey", - WindowWillBecomeMain: "mac:WindowWillBecomeMain", - WindowWillBeginSheet: "mac:WindowWillBeginSheet", - WindowWillChangeOrderingMode: "mac:WindowWillChangeOrderingMode", - WindowWillClose: "mac:WindowWillClose", - WindowWillDeminiaturize: "mac:WindowWillDeminiaturize", - WindowWillEnterFullScreen: "mac:WindowWillEnterFullScreen", - WindowWillEnterVersionBrowser: "mac:WindowWillEnterVersionBrowser", - WindowWillExitFullScreen: "mac:WindowWillExitFullScreen", - WindowWillExitVersionBrowser: "mac:WindowWillExitVersionBrowser", - WindowWillFocus: "mac:WindowWillFocus", - WindowWillMiniaturize: "mac:WindowWillMiniaturize", - WindowWillMove: "mac:WindowWillMove", - WindowWillOrderOffScreen: "mac:WindowWillOrderOffScreen", - WindowWillOrderOnScreen: "mac:WindowWillOrderOnScreen", - WindowWillResignMain: "mac:WindowWillResignMain", - WindowWillResize: "mac:WindowWillResize", - WindowWillUnfocus: "mac:WindowWillUnfocus", - WindowWillUpdate: "mac:WindowWillUpdate", - WindowWillUpdateAlpha: "mac:WindowWillUpdateAlpha", - WindowWillUpdateCollectionBehavior: "mac:WindowWillUpdateCollectionBehavior", - WindowWillUpdateCollectionProperties: "mac:WindowWillUpdateCollectionProperties", - WindowWillUpdateShadow: "mac:WindowWillUpdateShadow", - WindowWillUpdateTitle: "mac:WindowWillUpdateTitle", - WindowWillUpdateToolbar: "mac:WindowWillUpdateToolbar", - WindowWillUpdateVisibility: "mac:WindowWillUpdateVisibility", - WindowWillUseStandardFrame: "mac:WindowWillUseStandardFrame", - MenuWillOpen: "mac:MenuWillOpen", - MenuDidOpen: "mac:MenuDidOpen", - MenuDidClose: "mac:MenuDidClose", - MenuWillSendAction: "mac:MenuWillSendAction", - MenuDidSendAction: "mac:MenuDidSendAction", - MenuWillHighlightItem: "mac:MenuWillHighlightItem", - MenuDidHighlightItem: "mac:MenuDidHighlightItem", - MenuWillDisplayItem: "mac:MenuWillDisplayItem", - MenuDidDisplayItem: "mac:MenuDidDisplayItem", - MenuWillAddItem: "mac:MenuWillAddItem", - MenuDidAddItem: "mac:MenuDidAddItem", - MenuWillRemoveItem: "mac:MenuWillRemoveItem", - MenuDidRemoveItem: "mac:MenuDidRemoveItem", - MenuWillBeginTracking: "mac:MenuWillBeginTracking", - MenuDidBeginTracking: "mac:MenuDidBeginTracking", - MenuWillEndTracking: "mac:MenuWillEndTracking", - MenuDidEndTracking: "mac:MenuDidEndTracking", - MenuWillUpdate: "mac:MenuWillUpdate", - MenuDidUpdate: "mac:MenuDidUpdate", - MenuWillPopUp: "mac:MenuWillPopUp", - MenuDidPopUp: "mac:MenuDidPopUp", - MenuWillSendActionToItem: "mac:MenuWillSendActionToItem", - MenuDidSendActionToItem: "mac:MenuDidSendActionToItem", - WebViewDidStartProvisionalNavigation: "mac:WebViewDidStartProvisionalNavigation", - WebViewDidReceiveServerRedirectForProvisionalNavigation: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation", - WebViewDidFinishNavigation: "mac:WebViewDidFinishNavigation", - WebViewDidCommitNavigation: "mac:WebViewDidCommitNavigation", - WindowFileDraggingEntered: "mac:WindowFileDraggingEntered", - WindowFileDraggingPerformed: "mac:WindowFileDraggingPerformed", - WindowFileDraggingExited: "mac:WindowFileDraggingExited" - }, - Linux: { - SystemThemeChanged: "linux:SystemThemeChanged" - }, - Common: { - ApplicationStarted: "common:ApplicationStarted", - WindowMaximise: "common:WindowMaximise", - WindowUnMaximise: "common:WindowUnMaximise", - WindowFullscreen: "common:WindowFullscreen", - WindowUnFullscreen: "common:WindowUnFullscreen", - WindowRestore: "common:WindowRestore", - WindowMinimise: "common:WindowMinimise", - WindowUnMinimise: "common:WindowUnMinimise", - WindowClosing: "common:WindowClosing", - WindowZoom: "common:WindowZoom", - WindowZoomIn: "common:WindowZoomIn", - WindowZoomOut: "common:WindowZoomOut", - WindowZoomReset: "common:WindowZoomReset", - WindowFocus: "common:WindowFocus", - WindowLostFocus: "common:WindowLostFocus", - WindowShow: "common:WindowShow", - WindowHide: "common:WindowHide", - WindowDPIChanged: "common:WindowDPIChanged", - WindowFilesDropped: "common:WindowFilesDropped", - WindowRuntimeReady: "common:WindowRuntimeReady", - ThemeChanged: "common:ThemeChanged" - } - }; - - // desktop/@wailsio/runtime/src/events.js - var Types = EventTypes; - window._wails = window._wails || {}; - window._wails.dispatchWailsEvent = dispatchWailsEvent; - var call6 = newRuntimeCallerWithID(objectNames.Events, ""); - var EmitMethod = 0; - var eventListeners = /* @__PURE__ */ new Map(); - var Listener = class { - constructor(eventName, callback, maxCallbacks) { - this.eventName = eventName; - this.maxCallbacks = maxCallbacks || -1; - this.Callback = (data) => { - callback(data); - if (this.maxCallbacks === -1) - return false; - this.maxCallbacks -= 1; - return this.maxCallbacks === 0; - }; - } - }; - var WailsEvent = class { - constructor(name, data = null) { - this.name = name; - this.data = data; - } - }; - function setup() { - } - function dispatchWailsEvent(event) { - let listeners = eventListeners.get(event.name); - if (listeners) { - let toRemove = listeners.filter((listener) => { - let remove = listener.Callback(event); - if (remove) - return true; - }); - if (toRemove.length > 0) { - listeners = listeners.filter((l) => !toRemove.includes(l)); - if (listeners.length === 0) - eventListeners.delete(event.name); - else - eventListeners.set(event.name, listeners); - } - } - } - function OnMultiple(eventName, callback, maxCallbacks) { - let listeners = eventListeners.get(eventName) || []; - const thisListener = new Listener(eventName, callback, maxCallbacks); - listeners.push(thisListener); - eventListeners.set(eventName, listeners); - return () => listenerOff(thisListener); - } - function On(eventName, callback) { - return OnMultiple(eventName, callback, -1); - } - function Once(eventName, callback) { - return OnMultiple(eventName, callback, 1); - } - function listenerOff(listener) { - const eventName = listener.eventName; - let listeners = eventListeners.get(eventName).filter((l) => l !== listener); - if (listeners.length === 0) - eventListeners.delete(eventName); - else - eventListeners.set(eventName, listeners); - } - function Off(eventName, ...additionalEventNames) { - let eventsToRemove = [eventName, ...additionalEventNames]; - eventsToRemove.forEach((eventName2) => eventListeners.delete(eventName2)); - } - function OffAll() { - eventListeners.clear(); - } - function Emit(event) { - return call6(EmitMethod, event); - } - - // desktop/@wailsio/runtime/src/dialogs.js - var dialogs_exports = {}; - __export(dialogs_exports, { - Error: () => Error2, - Info: () => Info, - OpenFile: () => OpenFile, - Question: () => Question, - SaveFile: () => SaveFile, - Warning: () => Warning - }); - window._wails = window._wails || {}; - window._wails.dialogErrorCallback = dialogErrorCallback; - window._wails.dialogResultCallback = dialogResultCallback; - var DialogInfo = 0; - var DialogWarning = 1; - var DialogError = 2; - var DialogQuestion = 3; - var DialogOpenFile = 4; - var DialogSaveFile = 5; - var call7 = newRuntimeCallerWithID(objectNames.Dialog, ""); - var dialogResponses = /* @__PURE__ */ new Map(); - function generateID() { - let result; - do { - result = nanoid(); - } while (dialogResponses.has(result)); - return result; - } - function dialog(type, options = {}) { - const id = generateID(); - options["dialog-id"] = id; - return new Promise((resolve, reject) => { - dialogResponses.set(id, { resolve, reject }); - call7(type, options).catch((error) => { - reject(error); - dialogResponses.delete(id); - }); - }); - } - function dialogResultCallback(id, data, isJSON) { - let p = dialogResponses.get(id); - if (p) { - if (isJSON) { - p.resolve(JSON.parse(data)); - } else { - p.resolve(data); - } - dialogResponses.delete(id); - } - } - function dialogErrorCallback(id, message) { - let p = dialogResponses.get(id); - if (p) { - p.reject(message); - dialogResponses.delete(id); - } - } - var Info = (options) => dialog(DialogInfo, options); - var Warning = (options) => dialog(DialogWarning, options); - var Error2 = (options) => dialog(DialogError, options); - var Question = (options) => dialog(DialogQuestion, options); - var OpenFile = (options) => dialog(DialogOpenFile, options); - var SaveFile = (options) => dialog(DialogSaveFile, options); - - // desktop/@wailsio/runtime/src/wml.js - function sendEvent(eventName, data = null) { - let event = new WailsEvent(eventName, data); - Emit(event); - } - function addWMLEventListeners() { - const elements = document.querySelectorAll("[wml-event]"); - elements.forEach(function(element) { - const eventType = element.getAttribute("wml-event"); - const confirm = element.getAttribute("wml-confirm"); - const trigger = element.getAttribute("wml-trigger") || "click"; - let callback = function() { - if (confirm) { - Question({ Title: "Confirm", Message: confirm, Detached: false, Buttons: [{ Label: "Yes" }, { Label: "No", IsDefault: true }] }).then(function(result) { - if (result !== "No") { - sendEvent(eventType); - } - }); - return; - } - sendEvent(eventType); - }; - element.removeEventListener(trigger, callback); - element.addEventListener(trigger, callback); - }); - } - function callWindowMethod(windowName, method) { - let targetWindow = Get(windowName); - let methodMap = WindowMethods(targetWindow); - if (!methodMap.has(method)) { - console.log("Window method " + method + " not found"); - } - try { - methodMap.get(method)(); - } catch (e) { - console.error("Error calling window method '" + method + "': " + e); - } - } - function addWMLWindowListeners() { - const elements = document.querySelectorAll("[wml-window]"); - elements.forEach(function(element) { - const windowMethod = element.getAttribute("wml-window"); - const confirm = element.getAttribute("wml-confirm"); - const trigger = element.getAttribute("wml-trigger") || "click"; - const targetWindow = element.getAttribute("wml-target-window") || ""; - let callback = function() { - if (confirm) { - Question({ Title: "Confirm", Message: confirm, Buttons: [{ Label: "Yes" }, { Label: "No", IsDefault: true }] }).then(function(result) { - if (result !== "No") { - callWindowMethod(targetWindow, windowMethod); - } - }); - return; - } - callWindowMethod(targetWindow, windowMethod); - }; - element.removeEventListener(trigger, callback); - element.addEventListener(trigger, callback); - }); - } - function addWMLOpenBrowserListener() { - const elements = document.querySelectorAll("[wml-openurl]"); - elements.forEach(function(element) { - const url = element.getAttribute("wml-openurl"); - const confirm = element.getAttribute("wml-confirm"); - const trigger = element.getAttribute("wml-trigger") || "click"; - let callback = function() { - if (confirm) { - Question({ Title: "Confirm", Message: confirm, Buttons: [{ Label: "Yes" }, { Label: "No", IsDefault: true }] }).then(function(result) { - if (result !== "No") { - void OpenURL(url); - } - }); - return; - } - void OpenURL(url); - }; - element.removeEventListener(trigger, callback); - element.addEventListener(trigger, callback); - }); - } - function Reload() { - if (true) { - debugLog("Reloading WML"); - } - addWMLEventListeners(); - addWMLWindowListeners(); - addWMLOpenBrowserListener(); - } - function WindowMethods(targetWindow) { - let result = /* @__PURE__ */ new Map(); - for (let method in targetWindow) { - if (typeof targetWindow[method] === "function") { - result.set(method, targetWindow[method]); - } - } - return result; - } - - // desktop/@wailsio/runtime/src/calls.js - var calls_exports = {}; - __export(calls_exports, { - ByID: () => ByID, - ByName: () => ByName, - Call: () => Call, - Plugin: () => Plugin - }); - window._wails = window._wails || {}; - window._wails.callResultHandler = resultHandler; - window._wails.callErrorHandler = errorHandler; - var CallBinding = 0; - var call8 = newRuntimeCallerWithID(objectNames.Call, ""); - var callResponses = /* @__PURE__ */ new Map(); - function generateID2() { - let result; - do { - result = nanoid(); - } while (callResponses.has(result)); - return result; - } - function resultHandler(id, data, isJSON) { - const promiseHandler = getAndDeleteResponse(id); - if (promiseHandler) { - promiseHandler.resolve(isJSON ? JSON.parse(data) : data); - } - } - function errorHandler(id, message) { - const promiseHandler = getAndDeleteResponse(id); - if (promiseHandler) { - promiseHandler.reject(message); - } - } - function getAndDeleteResponse(id) { - const response = callResponses.get(id); - callResponses.delete(id); - return response; - } - function callBinding(type, options = {}) { - return new Promise((resolve, reject) => { - const id = generateID2(); - options["call-id"] = id; - callResponses.set(id, { resolve, reject }); - call8(type, options).catch((error) => { - reject(error); - callResponses.delete(id); - }); - }); - } - function Call(options) { - return callBinding(CallBinding, options); - } - function ByName(name, ...args) { - if (typeof name !== "string" || name.split(".").length !== 3) { - throw new Error("CallByName requires a string in the format 'package.struct.method'"); - } - let [packageName, structName, methodName] = name.split("."); - return callBinding(CallBinding, { - packageName, - structName, - methodName, - args - }); - } - function ByID(methodID, ...args) { - return callBinding(CallBinding, { - methodID, - args - }); - } - function Plugin(pluginName, methodName, ...args) { - return callBinding(CallBinding, { - packageName: "wails-plugins", - structName: pluginName, - methodName, - args - }); - } - - // desktop/compiled/main.js - window._wails = window._wails || {}; - window._wails.invoke = invoke; - window.wails = window.wails || {}; - window.wails.Application = application_exports; - window.wails.Browser = browser_exports; - window.wails.Call = calls_exports; - window.wails.Clipboard = clipboard_exports; - window.wails.Dialogs = dialogs_exports; - window.wails.Events = events_exports; - window.wails.Flags = flags_exports; - window.wails.Screens = screens_exports; - window.wails.System = system_exports; - window.wails.Window = window_exports; - window.wails.WML = wml_exports; - var isReady = false; - document.addEventListener("DOMContentLoaded", function() { - isReady = true; - window._wails.invoke("wails:runtime:ready"); - if (true) { - debugLog("Wails Runtime Loaded"); - } - }); - function whenReady(fn) { - if (isReady || document.readyState === "complete") { - fn(); - } else { - document.addEventListener("DOMContentLoaded", fn); - } - } - whenReady(() => { - Reload(); - }); -})(); -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb24uanMiLCAiLi4vLi4vLi4vcnVudGltZS9ub2RlX21vZHVsZXMvbmFub2lkL25vbi1zZWN1cmUvaW5kZXguanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3J1bnRpbWUuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXIuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZC5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3MuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3NjcmVlbnMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbS5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvd2luZG93LmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy93bWwuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50cy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZXZlbnRfdHlwZXMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RpYWxvZ3MuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NhbGxzLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9jb21waWxlZC9tYWluLmpzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcclxuICogTG9ncyBhIG1lc3NhZ2UgdG8gdGhlIGNvbnNvbGUgd2l0aCBjdXN0b20gZm9ybWF0dGluZy5cclxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQuXHJcbiAqIEByZXR1cm4ge3ZvaWR9XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZGVidWdMb2cobWVzc2FnZSkge1xyXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXHJcbiAgICBjb25zb2xlLmxvZyhcclxuICAgICAgICAnJWMgd2FpbHMzICVjICcgKyBtZXNzYWdlICsgJyAnLFxyXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjYWEwMDAwOyBjb2xvcjogI2ZmZjsgYm9yZGVyLXJhZGl1czogM3B4IDBweCAwcHggM3B4OyBwYWRkaW5nOiAxcHg7IGZvbnQtc2l6ZTogMC43cmVtJyxcclxuICAgICAgICAnYmFja2dyb3VuZDogIzAwOTkwMDsgY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDBweCAzcHggM3B4IDBweDsgcGFkZGluZzogMXB4OyBmb250LXNpemU6IDAuN3JlbSdcclxuICAgICk7XHJcbn0iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5cclxuaW1wb3J0IHsgbmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXMgfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkFwcGxpY2F0aW9uLCAnJyk7XHJcblxyXG5jb25zdCBIaWRlTWV0aG9kID0gMDtcclxuY29uc3QgU2hvd01ldGhvZCA9IDE7XHJcbmNvbnN0IFF1aXRNZXRob2QgPSAyO1xyXG5cclxuLyoqXHJcbiAqIEhpZGVzIGEgY2VydGFpbiBtZXRob2QgYnkgY2FsbGluZyB0aGUgSGlkZU1ldGhvZCBmdW5jdGlvbi5cclxuICpcclxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cclxuICpcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBIaWRlKCkge1xyXG4gICAgcmV0dXJuIGNhbGwoSGlkZU1ldGhvZCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDYWxscyB0aGUgU2hvd01ldGhvZCBhbmQgcmV0dXJucyB0aGUgcmVzdWx0LlxyXG4gKlxyXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNob3coKSB7XHJcbiAgICByZXR1cm4gY2FsbChTaG93TWV0aG9kKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENhbGxzIHRoZSBRdWl0TWV0aG9kIHRvIHRlcm1pbmF0ZSB0aGUgcHJvZ3JhbS5cclxuICpcclxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBRdWl0KCkge1xyXG4gICAgcmV0dXJuIGNhbGwoUXVpdE1ldGhvZCk7XHJcbn1cclxuIiwgImxldCB1cmxBbHBoYWJldCA9XG4gICd1c2VhbmRvbS0yNlQxOTgzNDBQWDc1cHhKQUNLVkVSWU1JTkRCVVNIV09MRl9HUVpiZmdoamtscXZ3eXpyaWN0J1xuZXhwb3J0IGxldCBjdXN0b21BbHBoYWJldCA9IChhbHBoYWJldCwgZGVmYXVsdFNpemUgPSAyMSkgPT4ge1xuICByZXR1cm4gKHNpemUgPSBkZWZhdWx0U2l6ZSkgPT4ge1xuICAgIGxldCBpZCA9ICcnXG4gICAgbGV0IGkgPSBzaXplXG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgaWQgKz0gYWxwaGFiZXRbKE1hdGgucmFuZG9tKCkgKiBhbHBoYWJldC5sZW5ndGgpIHwgMF1cbiAgICB9XG4gICAgcmV0dXJuIGlkXG4gIH1cbn1cbmV4cG9ydCBsZXQgbmFub2lkID0gKHNpemUgPSAyMSkgPT4ge1xuICBsZXQgaWQgPSAnJ1xuICBsZXQgaSA9IHNpemVcbiAgd2hpbGUgKGktLSkge1xuICAgIGlkICs9IHVybEFscGhhYmV0WyhNYXRoLnJhbmRvbSgpICogNjQpIHwgMF1cbiAgfVxuICByZXR1cm4gaWRcbn1cbiIsICIvKlxyXG4gXyAgICAgX18gICAgIF8gX19cclxufCB8ICAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXHJcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZC9ub24tc2VjdXJlJztcclxuXHJcbmNvbnN0IHJ1bnRpbWVVUkwgPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luICsgXCIvd2FpbHMvcnVudGltZVwiO1xyXG5cclxuLy8gT2JqZWN0IE5hbWVzXHJcbmV4cG9ydCBjb25zdCBvYmplY3ROYW1lcyA9IHtcclxuICAgIENhbGw6IDAsXHJcbiAgICBDbGlwYm9hcmQ6IDEsXHJcbiAgICBBcHBsaWNhdGlvbjogMixcclxuICAgIEV2ZW50czogMyxcclxuICAgIENvbnRleHRNZW51OiA0LFxyXG4gICAgRGlhbG9nOiA1LFxyXG4gICAgV2luZG93OiA2LFxyXG4gICAgU2NyZWVuczogNyxcclxuICAgIFN5c3RlbTogOCxcclxuICAgIEJyb3dzZXI6IDksXHJcbn1cclxuZXhwb3J0IGxldCBjbGllbnRJZCA9IG5hbm9pZCgpO1xyXG5cclxuLyoqXHJcbiAqIENyZWF0ZXMgYSBydW50aW1lIGNhbGxlciBmdW5jdGlvbiB0aGF0IGludm9rZXMgYSBzcGVjaWZpZWQgbWV0aG9kIG9uIGEgZ2l2ZW4gb2JqZWN0IHdpdGhpbiBhIHNwZWNpZmllZCB3aW5kb3cgY29udGV4dC5cclxuICpcclxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3Qgb24gd2hpY2ggdGhlIG1ldGhvZCBpcyB0byBiZSBpbnZva2VkLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgY29udGV4dCBpbiB3aGljaCB0aGUgbWV0aG9kIHNob3VsZCBiZSBjYWxsZWQuXHJcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gQSBydW50aW1lIGNhbGxlciBmdW5jdGlvbiB0aGF0IHRha2VzIHRoZSBtZXRob2QgbmFtZSBhbmQgb3B0aW9uYWxseSBhcmd1bWVudHMgYW5kIGludm9rZXMgdGhlIG1ldGhvZCB3aXRoaW4gdGhlIHNwZWNpZmllZCB3aW5kb3cgY29udGV4dC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdCwgd2luZG93TmFtZSkge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uIChtZXRob2QsIGFyZ3M9bnVsbCkge1xyXG4gICAgICAgIHJldHVybiBydW50aW1lQ2FsbChvYmplY3QgKyBcIi5cIiArIG1ldGhvZCwgd2luZG93TmFtZSwgYXJncyk7XHJcbiAgICB9O1xyXG59XHJcblxyXG4vKipcclxuICogQ3JlYXRlcyBhIG5ldyBydW50aW1lIGNhbGxlciB3aXRoIHNwZWNpZmllZCBJRC5cclxuICpcclxuICogQHBhcmFtIHtvYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3QgdG8gaW52b2tlIHRoZSBtZXRob2Qgb24uXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSB3aW5kb3dOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHdpbmRvdy5cclxuICogQHJldHVybiB7RnVuY3Rpb259IC0gVGhlIG5ldyBydW50aW1lIGNhbGxlciBmdW5jdGlvbi5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdCwgd2luZG93TmFtZSkge1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uIChtZXRob2QsIGFyZ3M9bnVsbCkge1xyXG4gICAgICAgIHJldHVybiBydW50aW1lQ2FsbFdpdGhJRChvYmplY3QsIG1ldGhvZCwgd2luZG93TmFtZSwgYXJncyk7XHJcbiAgICB9O1xyXG59XHJcblxyXG5cclxuZnVuY3Rpb24gcnVudGltZUNhbGwobWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKSB7XHJcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcclxuICAgIGlmKCBtZXRob2QgKSB7XHJcbiAgICAgICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJtZXRob2RcIiwgbWV0aG9kKTtcclxuICAgIH1cclxuICAgIGxldCBmZXRjaE9wdGlvbnMgPSB7XHJcbiAgICAgICAgaGVhZGVyczoge30sXHJcbiAgICB9O1xyXG4gICAgaWYgKHdpbmRvd05hbWUpIHtcclxuICAgICAgICBmZXRjaE9wdGlvbnMuaGVhZGVyc1tcIngtd2FpbHMtd2luZG93LW5hbWVcIl0gPSB3aW5kb3dOYW1lO1xyXG4gICAgfVxyXG4gICAgaWYgKGFyZ3MpIHtcclxuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcImFyZ3NcIiwgSlNPTi5zdHJpbmdpZnkoYXJncykpO1xyXG4gICAgfVxyXG4gICAgZmV0Y2hPcHRpb25zLmhlYWRlcnNbXCJ4LXdhaWxzLWNsaWVudC1pZFwiXSA9IGNsaWVudElkO1xyXG5cclxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgZmV0Y2godXJsLCBmZXRjaE9wdGlvbnMpXHJcbiAgICAgICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcclxuICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5vaykge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIGNoZWNrIGNvbnRlbnQgdHlwZVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKSAmJiByZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKS5pbmRleE9mKFwiYXBwbGljYXRpb24vanNvblwiKSAhPT0gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcihyZXNwb25zZS5zdGF0dXNUZXh0KSk7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIC50aGVuKGRhdGEgPT4gcmVzb2x2ZShkYXRhKSlcclxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHJ1bnRpbWVDYWxsV2l0aElEKG9iamVjdElELCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcclxuICAgIGxldCB1cmwgPSBuZXcgVVJMKHJ1bnRpbWVVUkwpO1xyXG4gICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJvYmplY3RcIiwgb2JqZWN0SUQpO1xyXG4gICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJtZXRob2RcIiwgbWV0aG9kKTtcclxuICAgIGxldCBmZXRjaE9wdGlvbnMgPSB7XHJcbiAgICAgICAgaGVhZGVyczoge30sXHJcbiAgICB9O1xyXG4gICAgaWYgKHdpbmRvd05hbWUpIHtcclxuICAgICAgICBmZXRjaE9wdGlvbnMuaGVhZGVyc1tcIngtd2FpbHMtd2luZG93LW5hbWVcIl0gPSB3aW5kb3dOYW1lO1xyXG4gICAgfVxyXG4gICAgaWYgKGFyZ3MpIHtcclxuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcImFyZ3NcIiwgSlNPTi5zdHJpbmdpZnkoYXJncykpO1xyXG4gICAgfVxyXG4gICAgZmV0Y2hPcHRpb25zLmhlYWRlcnNbXCJ4LXdhaWxzLWNsaWVudC1pZFwiXSA9IGNsaWVudElkO1xyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgICBmZXRjaCh1cmwsIGZldGNoT3B0aW9ucylcclxuICAgICAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLm9rKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgY29udGVudCB0eXBlXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpICYmIHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpLmluZGV4T2YoXCJhcHBsaWNhdGlvbi9qc29uXCIpICE9PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKHJlc3BvbnNlLnN0YXR1c1RleHQpKTtcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgLnRoZW4oZGF0YSA9PiByZXNvbHZlKGRhdGEpKVxyXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XHJcbiAgICB9KTtcclxufVxyXG4iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcblxyXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5Ccm93c2VyLCAnJyk7XHJcbmNvbnN0IEJyb3dzZXJPcGVuVVJMID0gMDtcclxuXHJcbi8qKlxyXG4gKiBPcGVuIGEgYnJvd3NlciB3aW5kb3cgdG8gdGhlIGdpdmVuIFVSTFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIC0gVGhlIFVSTCB0byBvcGVuXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gT3BlblVSTCh1cmwpIHtcclxuICAgIHJldHVybiBjYWxsKEJyb3dzZXJPcGVuVVJMLCB7dXJsfSk7XHJcbn1cclxuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcclxuXHJcbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkNsaXBib2FyZCwgJycpO1xyXG5jb25zdCBDbGlwYm9hcmRTZXRUZXh0ID0gMDtcclxuY29uc3QgQ2xpcGJvYXJkVGV4dCA9IDE7XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgdGV4dCB0byB0aGUgQ2xpcGJvYXJkLlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gdGV4dCAtIFRoZSB0ZXh0IHRvIGJlIHNldCB0byB0aGUgQ2xpcGJvYXJkLlxyXG4gKiBAcmV0dXJuIHtQcm9taXNlfSAtIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIG9wZXJhdGlvbiBpcyBzdWNjZXNzZnVsLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldFRleHQodGV4dCkge1xyXG4gICAgcmV0dXJuIGNhbGwoQ2xpcGJvYXJkU2V0VGV4dCwge3RleHR9KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldCB0aGUgQ2xpcGJvYXJkIHRleHRcclxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgdGV4dCBmcm9tIHRoZSBDbGlwYm9hcmQuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gVGV4dCgpIHtcclxuICAgIHJldHVybiBjYWxsKENsaXBib2FyZFRleHQpO1xyXG59XHJcbiIsICIvKlxyXG4gX1x0ICAgX19cdCAgXyBfX1xyXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXHJcblxyXG4vKipcclxuICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBrZXkgZnJvbSB0aGUgZmxhZyBtYXAuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXlTdHJpbmcgLSBUaGUga2V5IHRvIHJldHJpZXZlIHRoZSB2YWx1ZSBmb3IuXHJcbiAqIEByZXR1cm4geyp9IC0gVGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgc3BlY2lmaWVkIGtleS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBHZXRGbGFnKGtleVN0cmluZykge1xyXG4gICAgdHJ5IHtcclxuICAgICAgICByZXR1cm4gd2luZG93Ll93YWlscy5mbGFnc1trZXlTdHJpbmddO1xyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byByZXRyaWV2ZSBmbGFnICdcIiArIGtleVN0cmluZyArIFwiJzogXCIgKyBlKTtcclxuICAgIH1cclxufVxyXG4iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFBvc2l0aW9uXHJcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIFggY29vcmRpbmF0ZS5cclxuICogQHByb3BlcnR5IHtudW1iZXJ9IFkgLSBUaGUgWSBjb29yZGluYXRlLlxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBTaXplXHJcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIHdpZHRoLlxyXG4gKiBAcHJvcGVydHkge251bWJlcn0gWSAtIFRoZSBoZWlnaHQuXHJcbiAqL1xyXG5cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBSZWN0XHJcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIFggY29vcmRpbmF0ZSBvZiB0aGUgdG9wLWxlZnQgY29ybmVyLlxyXG4gKiBAcHJvcGVydHkge251bWJlcn0gWSAtIFRoZSBZIGNvb3JkaW5hdGUgb2YgdGhlIHRvcC1sZWZ0IGNvcm5lci5cclxuICogQHByb3BlcnR5IHtudW1iZXJ9IFdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSByZWN0YW5nbGUuXHJcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBIZWlnaHQgLSBUaGUgaGVpZ2h0IG9mIHRoZSByZWN0YW5nbGUuXHJcbiAqL1xyXG5cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7KCdaZXJvJ3wnTmluZXR5J3wnT25lRWlnaHR5J3wnVHdvU2V2ZW50eScpfSBSb3RhdGlvblxyXG4gKiBUaGUgcm90YXRpb24gb2YgdGhlIHNjcmVlbi4gQ2FuIGJlIG9uZSBvZiAnWmVybycsICdOaW5ldHknLCAnT25lRWlnaHR5JywgJ1R3b1NldmVudHknLlxyXG4gKi9cclxuXHJcblxyXG4vKipcclxuICogQHR5cGVkZWYge09iamVjdH0gU2NyZWVuXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBJZCAtIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgc2NyZWVuLlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTmFtZSAtIEh1bWFuIHJlYWRhYmxlIG5hbWUgb2YgdGhlIHNjcmVlbi5cclxuICogQHByb3BlcnR5IHtudW1iZXJ9IFNjYWxlIC0gVGhlIHJlc29sdXRpb24gc2NhbGUgb2YgdGhlIHNjcmVlbi4gMSA9IHN0YW5kYXJkIHJlc29sdXRpb24sIDIgPSBoaWdoIChSZXRpbmEpLCBldGMuXHJcbiAqIEBwcm9wZXJ0eSB7UG9zaXRpb259IFBvc2l0aW9uIC0gQ29udGFpbnMgdGhlIFggYW5kIFkgY29vcmRpbmF0ZXMgb2YgdGhlIHNjcmVlbidzIHBvc2l0aW9uLlxyXG4gKiBAcHJvcGVydHkge1NpemV9IFNpemUgLSBDb250YWlucyB0aGUgd2lkdGggYW5kIGhlaWdodCBvZiB0aGUgc2NyZWVuLlxyXG4gKiBAcHJvcGVydHkge1JlY3R9IEJvdW5kcyAtIENvbnRhaW5zIHRoZSBib3VuZHMgb2YgdGhlIHNjcmVlbiBpbiB0ZXJtcyBvZiBYLCBZLCBXaWR0aCwgYW5kIEhlaWdodC5cclxuICogQHByb3BlcnR5IHtSZWN0fSBXb3JrQXJlYSAtIENvbnRhaW5zIHRoZSBhcmVhIG9mIHRoZSBzY3JlZW4gdGhhdCBpcyBhY3R1YWxseSB1c2FibGUgKGV4Y2x1ZGluZyB0YXNrYmFyIGFuZCBvdGhlciBzeXN0ZW0gVUkpLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IElzUHJpbWFyeSAtIFRydWUgaWYgdGhpcyBpcyB0aGUgcHJpbWFyeSBtb25pdG9yIHNlbGVjdGVkIGJ5IHRoZSB1c2VyIGluIHRoZSBvcGVyYXRpbmcgc3lzdGVtLlxyXG4gKiBAcHJvcGVydHkge1JvdGF0aW9ufSBSb3RhdGlvbiAtIFRoZSByb3RhdGlvbiBvZiB0aGUgc2NyZWVuLlxyXG4gKi9cclxuXHJcblxyXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLlNjcmVlbnMsICcnKTtcclxuXHJcbmNvbnN0IGdldEFsbCA9IDA7XHJcbmNvbnN0IGdldFByaW1hcnkgPSAxO1xyXG5jb25zdCBnZXRDdXJyZW50ID0gMjtcclxuXHJcbi8qKlxyXG4gKiBHZXRzIGFsbCBzY3JlZW5zLlxyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxTY3JlZW5bXT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IG9mIFNjcmVlbiBvYmplY3RzLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEdldEFsbCgpIHtcclxuICAgIHJldHVybiBjYWxsKGdldEFsbCk7XHJcbn1cclxuLyoqXHJcbiAqIEdldHMgdGhlIHByaW1hcnkgc2NyZWVuLlxyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxTY3JlZW4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgcHJpbWFyeSBzY3JlZW4uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gR2V0UHJpbWFyeSgpIHtcclxuICAgIHJldHVybiBjYWxsKGdldFByaW1hcnkpO1xyXG59XHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBjdXJyZW50IGFjdGl2ZSBzY3JlZW4uXHJcbiAqXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPFNjcmVlbj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGN1cnJlbnQgYWN0aXZlIHNjcmVlbi5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBHZXRDdXJyZW50KCkge1xyXG4gICAgcmV0dXJuIGNhbGwoZ2V0Q3VycmVudCk7XHJcbn0iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xyXG5cclxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xyXG5sZXQgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU3lzdGVtLCAnJyk7XHJcbmNvbnN0IHN5c3RlbUlzRGFya01vZGUgPSAwO1xyXG5jb25zdCBlbnZpcm9ubWVudCA9IDE7XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gaW52b2tlKG1zZykge1xyXG4gICAgaWYod2luZG93LmNocm9tZSkge1xyXG4gICAgICAgIHJldHVybiB3aW5kb3cuY2hyb21lLndlYnZpZXcucG9zdE1lc3NhZ2UobXNnKTtcclxuICAgIH1cclxuICAgIHJldHVybiB3aW5kb3cud2Via2l0Lm1lc3NhZ2VIYW5kbGVycy5leHRlcm5hbC5wb3N0TWVzc2FnZTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBSZXRyaWV2ZXMgdGhlIHN5c3RlbSBkYXJrIG1vZGUgc3RhdHVzLlxyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxib29sZWFuPn0gLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIGJvb2xlYW4gdmFsdWUgaW5kaWNhdGluZyBpZiB0aGUgc3lzdGVtIGlzIGluIGRhcmsgbW9kZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBJc0RhcmtNb2RlKCkge1xyXG4gICAgcmV0dXJuIGNhbGwoc3lzdGVtSXNEYXJrTW9kZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBGZXRjaGVzIHRoZSBjYXBhYmlsaXRpZXMgb2YgdGhlIGFwcGxpY2F0aW9uIGZyb20gdGhlIHNlcnZlci5cclxuICpcclxuICogQGFzeW5jXHJcbiAqIEBmdW5jdGlvbiBDYXBhYmlsaXRpZXNcclxuICogQHJldHVybnMge1Byb21pc2U8T2JqZWN0Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGNhcGFiaWxpdGllcy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBDYXBhYmlsaXRpZXMoKSB7XHJcbiAgICBsZXQgcmVzcG9uc2UgPSBmZXRjaChcIi93YWlscy9jYXBhYmlsaXRpZXNcIik7XHJcbiAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xyXG59XHJcblxyXG4vKipcclxuICogQHR5cGVkZWYge29iamVjdH0gRW52aXJvbm1lbnRJbmZvXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBPUyAtIFRoZSBvcGVyYXRpbmcgc3lzdGVtIGluIHVzZS5cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IEFyY2ggLSBUaGUgYXJjaGl0ZWN0dXJlIG9mIHRoZSBzeXN0ZW0uXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBSZXRyaWV2ZXMgZW52aXJvbm1lbnQgZGV0YWlscy5cclxuICogQHJldHVybnMge1Byb21pc2U8RW52aXJvbm1lbnRJbmZvPn0gLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBvYmplY3QgY29udGFpbmluZyBPUyBhbmQgc3lzdGVtIGFyY2hpdGVjdHVyZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFbnZpcm9ubWVudCgpIHtcclxuICAgIHJldHVybiBjYWxsKGVudmlyb25tZW50KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIFdpbmRvd3MuXHJcbiAqXHJcbiAqIEByZXR1cm4ge2Jvb2xlYW59IFRydWUgaWYgdGhlIG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cywgb3RoZXJ3aXNlIGZhbHNlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIElzV2luZG93cygpIHtcclxuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcIndpbmRvd3NcIjtcclxufVxyXG5cclxuLyoqXHJcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIExpbnV4LlxyXG4gKlxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgTGludXgsIGZhbHNlIG90aGVyd2lzZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBJc0xpbnV4KCkge1xyXG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuT1MgPT09IFwibGludXhcIjtcclxufVxyXG5cclxuLyoqXHJcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBpcyBhIG1hY09TIG9wZXJhdGluZyBzeXN0ZW0uXHJcbiAqXHJcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBlbnZpcm9ubWVudCBpcyBtYWNPUywgZmFsc2Ugb3RoZXJ3aXNlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIElzTWFjKCkge1xyXG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuT1MgPT09IFwiZGFyd2luXCI7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgYXJjaGl0ZWN0dXJlIGlzIEFNRDY0LlxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQsIGZhbHNlIG90aGVyd2lzZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBJc0FNRDY0KCkge1xyXG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuQXJjaCA9PT0gXCJhbWQ2NFwiO1xyXG59XHJcblxyXG4vKipcclxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGFyY2hpdGVjdHVyZSBpcyBBUk0uXHJcbiAqXHJcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBjdXJyZW50IGFyY2hpdGVjdHVyZSBpcyBBUk0sIGZhbHNlIG90aGVyd2lzZS5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBJc0FSTSgpIHtcclxuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtXCI7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgaXMgQVJNNjQgYXJjaGl0ZWN0dXJlLlxyXG4gKlxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBSZXR1cm5zIHRydWUgaWYgdGhlIGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZSwgb3RoZXJ3aXNlIHJldHVybnMgZmFsc2UuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gSXNBUk02NCgpIHtcclxuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtNjRcIjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIElzRGVidWcoKSB7XHJcbiAgICByZXR1cm4gd2luZG93Ll93YWlscy5lbnZpcm9ubWVudC5EZWJ1ZyA9PT0gdHJ1ZTtcclxufVxyXG5cclxuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbi8vIEltcG9ydCBzY3JlZW4ganNkb2MgZGVmaW5pdGlvbiBmcm9tIC4vc2NyZWVucy5qc1xyXG4vKipcclxuICogQHR5cGVkZWYge2ltcG9ydChcIi4vc2NyZWVuc1wiKS5TY3JlZW59IFNjcmVlblxyXG4gKi9cclxuXHJcbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcclxuXHJcbmNvbnN0IGNlbnRlciA9IDA7XHJcbmNvbnN0IHNldFRpdGxlID0gMTtcclxuY29uc3QgZnVsbHNjcmVlbiA9IDI7XHJcbmNvbnN0IHVuRnVsbHNjcmVlbiA9IDM7XHJcbmNvbnN0IHNldFNpemUgPSA0O1xyXG5jb25zdCBzaXplID0gNTtcclxuY29uc3Qgc2V0TWF4U2l6ZSA9IDY7XHJcbmNvbnN0IHNldE1pblNpemUgPSA3O1xyXG5jb25zdCBzZXRBbHdheXNPblRvcCA9IDg7XHJcbmNvbnN0IHNldFJlbGF0aXZlUG9zaXRpb24gPSA5O1xyXG5jb25zdCByZWxhdGl2ZVBvc2l0aW9uID0gMTA7XHJcbmNvbnN0IHNjcmVlbiA9IDExO1xyXG5jb25zdCBoaWRlID0gMTI7XHJcbmNvbnN0IG1heGltaXNlID0gMTM7XHJcbmNvbnN0IHVuTWF4aW1pc2UgPSAxNDtcclxuY29uc3QgdG9nZ2xlTWF4aW1pc2UgPSAxNTtcclxuY29uc3QgbWluaW1pc2UgPSAxNjtcclxuY29uc3QgdW5NaW5pbWlzZSA9IDE3O1xyXG5jb25zdCByZXN0b3JlID0gMTg7XHJcbmNvbnN0IHNob3cgPSAxOTtcclxuY29uc3QgY2xvc2UgPSAyMDtcclxuY29uc3Qgc2V0QmFja2dyb3VuZENvbG91ciA9IDIxO1xyXG5jb25zdCBzZXRSZXNpemFibGUgPSAyMjtcclxuY29uc3Qgd2lkdGggPSAyMztcclxuY29uc3QgaGVpZ2h0ID0gMjQ7XHJcbmNvbnN0IHpvb21JbiA9IDI1O1xyXG5jb25zdCB6b29tT3V0ID0gMjY7XHJcbmNvbnN0IHpvb21SZXNldCA9IDI3O1xyXG5jb25zdCBnZXRab29tTGV2ZWwgPSAyODtcclxuY29uc3Qgc2V0Wm9vbUxldmVsID0gMjk7XHJcblxyXG5jb25zdCB0aGlzV2luZG93ID0gR2V0KCcnKTtcclxuXHJcbmZ1bmN0aW9uIGNyZWF0ZVdpbmRvdyhjYWxsKSB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIEdldDogKHdpbmRvd05hbWUpID0+IGNyZWF0ZVdpbmRvdyhuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLldpbmRvdywgd2luZG93TmFtZSkpLFxyXG4gICAgICAgIENlbnRlcjogKCkgPT4gY2FsbChjZW50ZXIpLFxyXG4gICAgICAgIFNldFRpdGxlOiAodGl0bGUpID0+IGNhbGwoc2V0VGl0bGUsIHt0aXRsZX0pLFxyXG4gICAgICAgIEZ1bGxzY3JlZW46ICgpID0+IGNhbGwoZnVsbHNjcmVlbiksXHJcbiAgICAgICAgVW5GdWxsc2NyZWVuOiAoKSA9PiBjYWxsKHVuRnVsbHNjcmVlbiksXHJcbiAgICAgICAgU2V0U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcclxuICAgICAgICBTaXplOiAoKSA9PiBjYWxsKHNpemUpLFxyXG4gICAgICAgIFNldE1heFNpemU6ICh3aWR0aCwgaGVpZ2h0KSA9PiBjYWxsKHNldE1heFNpemUsIHt3aWR0aCwgaGVpZ2h0fSksXHJcbiAgICAgICAgU2V0TWluU2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWluU2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcclxuICAgICAgICBTZXRBbHdheXNPblRvcDogKG9uVG9wKSA9PiBjYWxsKHNldEFsd2F5c09uVG9wLCB7YWx3YXlzT25Ub3A6IG9uVG9wfSksXHJcbiAgICAgICAgU2V0UmVsYXRpdmVQb3NpdGlvbjogKHgsIHkpID0+IGNhbGwoc2V0UmVsYXRpdmVQb3NpdGlvbiwge3gsIHl9KSxcclxuICAgICAgICBSZWxhdGl2ZVBvc2l0aW9uOiAoKSA9PiBjYWxsKHJlbGF0aXZlUG9zaXRpb24pLFxyXG4gICAgICAgIFNjcmVlbjogKCkgPT4gY2FsbChzY3JlZW4pLFxyXG4gICAgICAgIEhpZGU6ICgpID0+IGNhbGwoaGlkZSksXHJcbiAgICAgICAgTWF4aW1pc2U6ICgpID0+IGNhbGwobWF4aW1pc2UpLFxyXG4gICAgICAgIFVuTWF4aW1pc2U6ICgpID0+IGNhbGwodW5NYXhpbWlzZSksXHJcbiAgICAgICAgVG9nZ2xlTWF4aW1pc2U6ICgpID0+IGNhbGwodG9nZ2xlTWF4aW1pc2UpLFxyXG4gICAgICAgIE1pbmltaXNlOiAoKSA9PiBjYWxsKG1pbmltaXNlKSxcclxuICAgICAgICBVbk1pbmltaXNlOiAoKSA9PiBjYWxsKHVuTWluaW1pc2UpLFxyXG4gICAgICAgIFJlc3RvcmU6ICgpID0+IGNhbGwocmVzdG9yZSksXHJcbiAgICAgICAgU2hvdzogKCkgPT4gY2FsbChzaG93KSxcclxuICAgICAgICBDbG9zZTogKCkgPT4gY2FsbChjbG9zZSksXHJcbiAgICAgICAgU2V0QmFja2dyb3VuZENvbG91cjogKHIsIGcsIGIsIGEpID0+IGNhbGwoc2V0QmFja2dyb3VuZENvbG91ciwge3IsIGcsIGIsIGF9KSxcclxuICAgICAgICBTZXRSZXNpemFibGU6IChyZXNpemFibGUpID0+IGNhbGwoc2V0UmVzaXphYmxlLCB7cmVzaXphYmxlfSksXHJcbiAgICAgICAgV2lkdGg6ICgpID0+IGNhbGwod2lkdGgpLFxyXG4gICAgICAgIEhlaWdodDogKCkgPT4gY2FsbChoZWlnaHQpLFxyXG4gICAgICAgIFpvb21JbjogKCkgPT4gY2FsbCh6b29tSW4pLFxyXG4gICAgICAgIFpvb21PdXQ6ICgpID0+IGNhbGwoem9vbU91dCksXHJcbiAgICAgICAgWm9vbVJlc2V0OiAoKSA9PiBjYWxsKHpvb21SZXNldCksXHJcbiAgICAgICAgR2V0Wm9vbUxldmVsOiAoKSA9PiBjYWxsKGdldFpvb21MZXZlbCksXHJcbiAgICAgICAgU2V0Wm9vbUxldmVsOiAoem9vbUxldmVsKSA9PiBjYWxsKHNldFpvb21MZXZlbCwge3pvb21MZXZlbH0pLFxyXG4gICAgfTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIHNwZWNpZmllZCB3aW5kb3cuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSB3aW5kb3dOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHdpbmRvdyB0byBnZXQuXHJcbiAqIEByZXR1cm4ge09iamVjdH0gLSBUaGUgc3BlY2lmaWVkIHdpbmRvdyBvYmplY3QuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gR2V0KHdpbmRvd05hbWUpIHtcclxuICAgIHJldHVybiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENlbnRlcnMgdGhlIHdpbmRvdyBvbiB0aGUgc2NyZWVuLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIENlbnRlcigpIHtcclxuICAgIHRoaXNXaW5kb3cuQ2VudGVyKCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXRzIHRoZSB0aXRsZSBvZiB0aGUgd2luZG93LlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGUgLSBUaGUgdGl0bGUgdG8gc2V0LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldFRpdGxlKHRpdGxlKSB7XHJcbiAgICB0aGlzV2luZG93LlNldFRpdGxlKHRpdGxlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIHdpbmRvdyB0byBmdWxsc2NyZWVuLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEZ1bGxzY3JlZW4oKSB7XHJcbiAgICB0aGlzV2luZG93LkZ1bGxzY3JlZW4oKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIHNpemUgb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgLSBUaGUgaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2V0U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XHJcbiAgICB0aGlzV2luZG93LlNldFNpemUod2lkdGgsIGhlaWdodCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBzaXplIG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2l6ZSgpIHtcclxuICAgIHJldHVybiB0aGlzV2luZG93LlNpemUoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93LlxyXG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGggLSBUaGUgbWF4aW11bSB3aWR0aCBvZiB0aGUgd2luZG93LlxyXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIG1heGltdW0gaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XHJcbiAgICB0aGlzV2luZG93LlNldE1heFNpemUod2lkdGgsIGhlaWdodCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXRzIHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIG1pbmltdW0gd2lkdGggb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodCAtIFRoZSBtaW5pbXVtIGhlaWdodCBvZiB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldE1pblNpemUod2lkdGgsIGhlaWdodCkge1xyXG4gICAgdGhpc1dpbmRvdy5TZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgd2luZG93IHRvIGFsd2F5cyBiZSBvbiB0b3AuXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gb25Ub3AgLSBXaGV0aGVyIHRoZSB3aW5kb3cgc2hvdWxkIGFsd2F5cyBiZSBvbiB0b3AuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2V0QWx3YXlzT25Ub3Aob25Ub3ApIHtcclxuICAgIHRoaXNXaW5kb3cuU2V0QWx3YXlzT25Ub3Aob25Ub3ApO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHggLSBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSB3aW5kb3cncyBwb3NpdGlvbi5cclxuICogQHBhcmFtIHtudW1iZXJ9IHkgLSBUaGUgeS1jb29yZGluYXRlIG9mIHRoZSB3aW5kb3cncyBwb3NpdGlvbi5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTZXRSZWxhdGl2ZVBvc2l0aW9uKHgsIHkpIHtcclxuICAgIHRoaXNXaW5kb3cuU2V0UmVsYXRpdmVQb3NpdGlvbih4LCB5KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gUmVsYXRpdmVQb3NpdGlvbigpIHtcclxuICAgIHJldHVybiB0aGlzV2luZG93LlJlbGF0aXZlUG9zaXRpb24oKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIHNjcmVlbiB0aGF0IHRoZSB3aW5kb3cgaXMgb24uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gU2NyZWVuKCkge1xyXG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2NyZWVuKCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBIaWRlcyB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XHJcbiAgICB0aGlzV2luZG93LkhpZGUoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE1heGltaXNlcyB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIE1heGltaXNlKCkge1xyXG4gICAgdGhpc1dpbmRvdy5NYXhpbWlzZSgpO1xyXG59XHJcblxyXG4vKipcclxuICogVW4tbWF4aW1pc2VzIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gVW5NYXhpbWlzZSgpIHtcclxuICAgIHRoaXNXaW5kb3cuVW5NYXhpbWlzZSgpO1xyXG59XHJcblxyXG4vKipcclxuICogVG9nZ2xlcyB0aGUgbWF4aW1pc2F0aW9uIG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gVG9nZ2xlTWF4aW1pc2UoKSB7XHJcbiAgICB0aGlzV2luZG93LlRvZ2dsZU1heGltaXNlKCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBNaW5pbWlzZXMgdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBNaW5pbWlzZSgpIHtcclxuICAgIHRoaXNXaW5kb3cuTWluaW1pc2UoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFVuLW1pbmltaXNlcyB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFVuTWluaW1pc2UoKSB7XHJcbiAgICB0aGlzV2luZG93LlVuTWluaW1pc2UoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlc3RvcmVzIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gUmVzdG9yZSgpIHtcclxuICAgIHRoaXNXaW5kb3cuUmVzdG9yZSgpO1xyXG59XHJcblxyXG4vKipcclxuICogU2hvd3MgdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTaG93KCkge1xyXG4gICAgdGhpc1dpbmRvdy5TaG93KCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDbG9zZXMgdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBDbG9zZSgpIHtcclxuICAgIHRoaXNXaW5kb3cuQ2xvc2UoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIGJhY2tncm91bmQgY29sb3VyIG9mIHRoZSB3aW5kb3cuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSByIC0gVGhlIHJlZCBjb21wb25lbnQgb2YgdGhlIGNvbG91ci5cclxuICogQHBhcmFtIHtudW1iZXJ9IGcgLSBUaGUgZ3JlZW4gY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBiIC0gVGhlIGJsdWUgY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBhIC0gVGhlIGFscGhhIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldEJhY2tncm91bmRDb2xvdXIociwgZywgYiwgYSkge1xyXG4gICAgdGhpc1dpbmRvdy5TZXRCYWNrZ3JvdW5kQ29sb3VyKHIsIGcsIGIsIGEpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgcmVzaXphYmxlLlxyXG4gKiBAcGFyYW0ge2Jvb2xlYW59IHJlc2l6YWJsZSAtIFdoZXRoZXIgdGhlIHdpbmRvdyBzaG91bGQgYmUgcmVzaXphYmxlLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldFJlc2l6YWJsZShyZXNpemFibGUpIHtcclxuICAgIHRoaXNXaW5kb3cuU2V0UmVzaXphYmxlKHJlc2l6YWJsZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSB3aWR0aCBvZiB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpZHRoKCkge1xyXG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuV2lkdGgoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEhlaWdodCgpIHtcclxuICAgIHJldHVybiB0aGlzV2luZG93LkhlaWdodCgpO1xyXG59XHJcblxyXG4vKipcclxuICogWm9vbXMgaW4gdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBab29tSW4oKSB7XHJcbiAgICB0aGlzV2luZG93Llpvb21JbigpO1xyXG59XHJcblxyXG4vKipcclxuICogWm9vbXMgb3V0IHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gWm9vbU91dCgpIHtcclxuICAgIHRoaXNXaW5kb3cuWm9vbU91dCgpO1xyXG59XHJcblxyXG4vKipcclxuICogUmVzZXRzIHRoZSB6b29tIG9mIHRoZSB3aW5kb3cuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gWm9vbVJlc2V0KCkge1xyXG4gICAgdGhpc1dpbmRvdy5ab29tUmVzZXQoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHdpbmRvdy5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBHZXRab29tTGV2ZWwoKSB7XHJcbiAgICByZXR1cm4gdGhpc1dpbmRvdy5HZXRab29tTGV2ZWwoKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIHpvb20gbGV2ZWwgb2YgdGhlIHdpbmRvdy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHpvb21MZXZlbCAtIFRoZSB6b29tIGxldmVsIHRvIHNldC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTZXRab29tTGV2ZWwoem9vbUxldmVsKSB7XHJcbiAgICB0aGlzV2luZG93LlNldFpvb21MZXZlbCh6b29tTGV2ZWwpO1xyXG59XHJcbiIsICJcclxuaW1wb3J0IHtFbWl0LCBXYWlsc0V2ZW50fSBmcm9tIFwiLi9ldmVudHNcIjtcclxuaW1wb3J0IHtRdWVzdGlvbn0gZnJvbSBcIi4vZGlhbG9nc1wiO1xyXG5pbXBvcnQge0dldH0gZnJvbSBcIi4vd2luZG93XCI7XHJcbmltcG9ydCB7T3BlblVSTH0gZnJvbSBcIi4vYnJvd3NlclwiO1xyXG5pbXBvcnQge2RlYnVnTG9nfSBmcm9tIFwiLi9sb2dcIjtcclxuXHJcbi8qKlxyXG4gKiBTZW5kcyBhbiBldmVudCB3aXRoIHRoZSBnaXZlbiBuYW1lIGFuZCBvcHRpb25hbCBkYXRhLlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHNlbmQuXHJcbiAqIEBwYXJhbSB7YW55fSBbZGF0YT1udWxsXSAtIE9wdGlvbmFsIGRhdGEgdG8gc2VuZCBhbG9uZyB3aXRoIHRoZSBldmVudC5cclxuICpcclxuICogQHJldHVybiB7dm9pZH1cclxuICovXHJcbmZ1bmN0aW9uIHNlbmRFdmVudChldmVudE5hbWUsIGRhdGE9bnVsbCkge1xyXG4gICAgbGV0IGV2ZW50ID0gbmV3IFdhaWxzRXZlbnQoZXZlbnROYW1lLCBkYXRhKTtcclxuICAgIEVtaXQoZXZlbnQpO1xyXG59XHJcblxyXG4vKipcclxuICogQWRkcyBldmVudCBsaXN0ZW5lcnMgdG8gZWxlbWVudHMgd2l0aCBgd21sLWV2ZW50YCBhdHRyaWJ1dGUuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3ZvaWR9XHJcbiAqL1xyXG5mdW5jdGlvbiBhZGRXTUxFdmVudExpc3RlbmVycygpIHtcclxuICAgIGNvbnN0IGVsZW1lbnRzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnW3dtbC1ldmVudF0nKTtcclxuICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHtcclxuICAgICAgICBjb25zdCBldmVudFR5cGUgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWV2ZW50Jyk7XHJcbiAgICAgICAgY29uc3QgY29uZmlybSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtY29uZmlybScpO1xyXG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XHJcblxyXG4gICAgICAgIGxldCBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcclxuICAgICAgICAgICAgICAgIFF1ZXN0aW9uKHtUaXRsZTogXCJDb25maXJtXCIsIE1lc3NhZ2U6Y29uZmlybSwgRGV0YWNoZWQ6IGZhbHNlLCBCdXR0b25zOlt7TGFiZWw6XCJZZXNcIn0se0xhYmVsOlwiTm9cIiwgSXNEZWZhdWx0OnRydWV9XX0pLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT09IFwiTm9cIikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kRXZlbnQoZXZlbnRUeXBlKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBzZW5kRXZlbnQoZXZlbnRUeXBlKTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvLyBSZW1vdmUgZXhpc3RpbmcgbGlzdGVuZXJzXHJcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcclxuXHJcbiAgICAgICAgLy8gQWRkIG5ldyBsaXN0ZW5lclxyXG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBDYWxscyBhIG1ldGhvZCBvbiBhIHNwZWNpZmllZCB3aW5kb3cuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSB3aW5kb3dOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHdpbmRvdyB0byBjYWxsIHRoZSBtZXRob2Qgb24uXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2QgLSBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXHJcbiAqL1xyXG5mdW5jdGlvbiBjYWxsV2luZG93TWV0aG9kKHdpbmRvd05hbWUsIG1ldGhvZCkge1xyXG4gICAgbGV0IHRhcmdldFdpbmRvdyA9IEdldCh3aW5kb3dOYW1lKTtcclxuICAgIGxldCBtZXRob2RNYXAgPSBXaW5kb3dNZXRob2RzKHRhcmdldFdpbmRvdyk7XHJcbiAgICBpZiAoIW1ldGhvZE1hcC5oYXMobWV0aG9kKSkge1xyXG4gICAgICAgIGNvbnNvbGUubG9nKFwiV2luZG93IG1ldGhvZCBcIiArIG1ldGhvZCArIFwiIG5vdCBmb3VuZFwiKTtcclxuICAgIH1cclxuICAgIHRyeSB7XHJcbiAgICAgICAgbWV0aG9kTWFwLmdldChtZXRob2QpKCk7XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIGNhbGxpbmcgd2luZG93IG1ldGhvZCAnXCIgKyBtZXRob2QgKyBcIic6IFwiICsgZSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBBZGRzIHdpbmRvdyBsaXN0ZW5lcnMgZm9yIGVsZW1lbnRzIHdpdGggdGhlICd3bWwtd2luZG93JyBhdHRyaWJ1dGUuXHJcbiAqIFJlbW92ZXMgYW55IGV4aXN0aW5nIGxpc3RlbmVycyBiZWZvcmUgYWRkaW5nIG5ldyBvbmVzLlxyXG4gKlxyXG4gKiBAcmV0dXJuIHt2b2lkfVxyXG4gKi9cclxuZnVuY3Rpb24gYWRkV01MV2luZG93TGlzdGVuZXJzKCkge1xyXG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLXdpbmRvd10nKTtcclxuICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHtcclxuICAgICAgICBjb25zdCB3aW5kb3dNZXRob2QgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXdpbmRvdycpO1xyXG4gICAgICAgIGNvbnN0IGNvbmZpcm0gPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWNvbmZpcm0nKTtcclxuICAgICAgICBjb25zdCB0cmlnZ2VyID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC10cmlnZ2VyJykgfHwgJ2NsaWNrJztcclxuICAgICAgICBjb25zdCB0YXJnZXRXaW5kb3cgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRhcmdldC13aW5kb3cnKSB8fCAnJztcclxuXHJcbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAoY29uZmlybSkge1xyXG4gICAgICAgICAgICAgICAgUXVlc3Rpb24oe1RpdGxlOiBcIkNvbmZpcm1cIiwgTWVzc2FnZTpjb25maXJtLCBCdXR0b25zOlt7TGFiZWw6XCJZZXNcIn0se0xhYmVsOlwiTm9cIiwgSXNEZWZhdWx0OnRydWV9XX0pLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT09IFwiTm9cIikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYWxsV2luZG93TWV0aG9kKHRhcmdldFdpbmRvdywgd2luZG93TWV0aG9kKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYWxsV2luZG93TWV0aG9kKHRhcmdldFdpbmRvdywgd2luZG93TWV0aG9kKTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvLyBSZW1vdmUgZXhpc3RpbmcgbGlzdGVuZXJzXHJcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcclxuXHJcbiAgICAgICAgLy8gQWRkIG5ldyBsaXN0ZW5lclxyXG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEFkZHMgYSBsaXN0ZW5lciB0byBlbGVtZW50cyB3aXRoIHRoZSAnd21sLW9wZW51cmwnIGF0dHJpYnV0ZS5cclxuICogV2hlbiB0aGUgc3BlY2lmaWVkIHRyaWdnZXIgZXZlbnQgaXMgZmlyZWQgb24gYW55IG9mIHRoZXNlIGVsZW1lbnRzLFxyXG4gKiB0aGUgbGlzdGVuZXIgd2lsbCBvcGVuIHRoZSBVUkwgc3BlY2lmaWVkIGJ5IHRoZSAnd21sLW9wZW51cmwnIGF0dHJpYnV0ZS5cclxuICogSWYgYSAnd21sLWNvbmZpcm0nIGF0dHJpYnV0ZSBpcyBwcm92aWRlZCwgYSBjb25maXJtYXRpb24gZGlhbG9nIHdpbGwgYmUgZGlzcGxheWVkLFxyXG4gKiBhbmQgdGhlIFVSTCB3aWxsIG9ubHkgYmUgb3BlbmVkIGlmIHRoZSB1c2VyIGNvbmZpcm1zLlxyXG4gKlxyXG4gKiBAcmV0dXJuIHt2b2lkfVxyXG4gKi9cclxuZnVuY3Rpb24gYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpIHtcclxuICAgIGNvbnN0IGVsZW1lbnRzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnW3dtbC1vcGVudXJsXScpO1xyXG4gICAgZWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbiAoZWxlbWVudCkge1xyXG4gICAgICAgIGNvbnN0IHVybCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtb3BlbnVybCcpO1xyXG4gICAgICAgIGNvbnN0IGNvbmZpcm0gPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWNvbmZpcm0nKTtcclxuICAgICAgICBjb25zdCB0cmlnZ2VyID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC10cmlnZ2VyJykgfHwgXCJjbGlja1wiO1xyXG5cclxuICAgICAgICBsZXQgY2FsbGJhY2sgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChjb25maXJtKSB7XHJcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIEJ1dHRvbnM6W3tMYWJlbDpcIlllc1wifSx7TGFiZWw6XCJOb1wiLCBJc0RlZmF1bHQ6dHJ1ZX1dfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPT0gXCJOb1wiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZvaWQgT3BlblVSTCh1cmwpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHZvaWQgT3BlblVSTCh1cmwpO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8vIFJlbW92ZSBleGlzdGluZyBsaXN0ZW5lcnNcclxuICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xyXG5cclxuICAgICAgICAvLyBBZGQgbmV3IGxpc3RlbmVyXHJcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogUmVsb2FkcyB0aGUgV01MIHBhZ2UgYnkgYWRkaW5nIG5lY2Vzc2FyeSBldmVudCBsaXN0ZW5lcnMgYW5kIGJyb3dzZXIgbGlzdGVuZXJzLlxyXG4gKlxyXG4gKiBAcmV0dXJuIHt2b2lkfVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFJlbG9hZCgpIHtcclxuICAgIGlmKERFQlVHKSB7XHJcbiAgICAgICAgZGVidWdMb2coXCJSZWxvYWRpbmcgV01MXCIpO1xyXG4gICAgfVxyXG4gICAgYWRkV01MRXZlbnRMaXN0ZW5lcnMoKTtcclxuICAgIGFkZFdNTFdpbmRvd0xpc3RlbmVycygpO1xyXG4gICAgYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpO1xyXG59XHJcblxyXG4vKipcclxuICogUmV0dXJucyBhIG1hcCBvZiBhbGwgbWV0aG9kcyBpbiB0aGUgY3VycmVudCB3aW5kb3cuXHJcbiAqIEByZXR1cm5zIHtNYXB9IC0gQSBtYXAgb2Ygd2luZG93IG1ldGhvZHMuXHJcbiAqL1xyXG5mdW5jdGlvbiBXaW5kb3dNZXRob2RzKHRhcmdldFdpbmRvdykge1xyXG4gICAgLy8gQ3JlYXRlIGEgbmV3IG1hcCB0byBzdG9yZSBtZXRob2RzXHJcbiAgICBsZXQgcmVzdWx0ID0gbmV3IE1hcCgpO1xyXG5cclxuICAgIC8vIEl0ZXJhdGUgb3ZlciBhbGwgcHJvcGVydGllcyBvZiB0aGUgd2luZG93IG9iamVjdFxyXG4gICAgZm9yIChsZXQgbWV0aG9kIGluIHRhcmdldFdpbmRvdykge1xyXG4gICAgICAgIC8vIENoZWNrIGlmIHRoZSBwcm9wZXJ0eSBpcyBpbmRlZWQgYSBtZXRob2QgKGZ1bmN0aW9uKVxyXG4gICAgICAgIGlmKHR5cGVvZiB0YXJnZXRXaW5kb3dbbWV0aG9kXSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgICAvLyBBZGQgdGhlIG1ldGhvZCB0byB0aGUgbWFwXHJcbiAgICAgICAgICAgIHJlc3VsdC5zZXQobWV0aG9kLCB0YXJnZXRXaW5kb3dbbWV0aG9kXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgIH1cclxuICAgIC8vIFJldHVybiB0aGUgbWFwIG9mIHdpbmRvdyBtZXRob2RzXHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59IiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7aW1wb3J0KFwiLi90eXBlc1wiKS5XYWlsc0V2ZW50fSBXYWlsc0V2ZW50XHJcbiAqL1xyXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcblxyXG5pbXBvcnQge0V2ZW50VHlwZXN9IGZyb20gXCIuL2V2ZW50X3R5cGVzXCI7XHJcbmV4cG9ydCBjb25zdCBUeXBlcyA9IEV2ZW50VHlwZXM7XHJcblxyXG4vLyBTZXR1cFxyXG53aW5kb3cuX3dhaWxzID0gd2luZG93Ll93YWlscyB8fCB7fTtcclxud2luZG93Ll93YWlscy5kaXNwYXRjaFdhaWxzRXZlbnQgPSBkaXNwYXRjaFdhaWxzRXZlbnQ7XHJcblxyXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5FdmVudHMsICcnKTtcclxuY29uc3QgRW1pdE1ldGhvZCA9IDA7XHJcbmNvbnN0IGV2ZW50TGlzdGVuZXJzID0gbmV3IE1hcCgpO1xyXG5cclxuY2xhc3MgTGlzdGVuZXIge1xyXG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XHJcbiAgICAgICAgdGhpcy5ldmVudE5hbWUgPSBldmVudE5hbWU7XHJcbiAgICAgICAgdGhpcy5tYXhDYWxsYmFja3MgPSBtYXhDYWxsYmFja3MgfHwgLTE7XHJcbiAgICAgICAgdGhpcy5DYWxsYmFjayA9IChkYXRhKSA9PiB7XHJcbiAgICAgICAgICAgIGNhbGxiYWNrKGRhdGEpO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhDYWxsYmFja3MgPT09IC0xKSByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIHRoaXMubWF4Q2FsbGJhY2tzIC09IDE7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1heENhbGxiYWNrcyA9PT0gMDtcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgV2FpbHNFdmVudCB7XHJcbiAgICBjb25zdHJ1Y3RvcihuYW1lLCBkYXRhID0gbnVsbCkge1xyXG4gICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XHJcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIHNldHVwKCkge1xyXG59XHJcblxyXG5mdW5jdGlvbiBkaXNwYXRjaFdhaWxzRXZlbnQoZXZlbnQpIHtcclxuICAgIGxldCBsaXN0ZW5lcnMgPSBldmVudExpc3RlbmVycy5nZXQoZXZlbnQubmFtZSk7XHJcbiAgICBpZiAobGlzdGVuZXJzKSB7XHJcbiAgICAgICAgbGV0IHRvUmVtb3ZlID0gbGlzdGVuZXJzLmZpbHRlcihsaXN0ZW5lciA9PiB7XHJcbiAgICAgICAgICAgIGxldCByZW1vdmUgPSBsaXN0ZW5lci5DYWxsYmFjayhldmVudCk7XHJcbiAgICAgICAgICAgIGlmIChyZW1vdmUpIHJldHVybiB0cnVlO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIGlmICh0b1JlbW92ZS5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVycy5maWx0ZXIobCA9PiAhdG9SZW1vdmUuaW5jbHVkZXMobCkpO1xyXG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkgZXZlbnRMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50Lm5hbWUpO1xyXG4gICAgICAgICAgICBlbHNlIGV2ZW50TGlzdGVuZXJzLnNldChldmVudC5uYW1lLCBsaXN0ZW5lcnMpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzIGZvciBhIHNwZWNpZmljIGV2ZW50LlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmb3IuXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3MgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdGhlIGNhbGxiYWNrIGNhbiBiZSBjYWxsZWQgZm9yIHRoZSBldmVudC4gT25jZSB0aGUgbWF4aW11bSBudW1iZXIgaXMgcmVhY2hlZCwgdGhlIGNhbGxiYWNrIHdpbGwgbm8gbG9uZ2VyIGJlIGNhbGxlZC5cclxuICpcclxuIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpIHtcclxuICAgIGxldCBsaXN0ZW5lcnMgPSBldmVudExpc3RlbmVycy5nZXQoZXZlbnROYW1lKSB8fCBbXTtcclxuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xyXG4gICAgbGlzdGVuZXJzLnB1c2godGhpc0xpc3RlbmVyKTtcclxuICAgIGV2ZW50TGlzdGVuZXJzLnNldChldmVudE5hbWUsIGxpc3RlbmVycyk7XHJcbiAgICByZXR1cm4gKCkgPT4gbGlzdGVuZXJPZmYodGhpc0xpc3RlbmVyKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlZ2lzdGVycyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIHNwZWNpZmllZCBldmVudCBvY2N1cnMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkLiBJdCB0YWtlcyBubyBwYXJhbWV0ZXJzLlxyXG4gKiBAcmV0dXJuIHtmdW5jdGlvbn0gLSBBIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCB3aWxsIHVucmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZyb20gdGhlIGV2ZW50LiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gT24oZXZlbnROYW1lLCBjYWxsYmFjaykgeyByZXR1cm4gT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAtMSk7IH1cclxuXHJcbi8qKlxyXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmx5IG9uY2UgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGV2ZW50IG9jY3Vycy5cclxuICogQHJldHVybiB7ZnVuY3Rpb259IC0gQSBmdW5jdGlvbiB0aGF0LCB3aGVuIGNhbGxlZCwgd2lsbCB1bnJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmcm9tIHRoZSBldmVudC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHsgcmV0dXJuIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgMSk7IH1cclxuXHJcbi8qKlxyXG4gKiBSZW1vdmVzIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIgZnJvbSB0aGUgZXZlbnQgbGlzdGVuZXJzIGNvbGxlY3Rpb24uXHJcbiAqIElmIGFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBldmVudCBhcmUgcmVtb3ZlZCwgdGhlIGV2ZW50IGtleSBpcyBkZWxldGVkIGZyb20gdGhlIGNvbGxlY3Rpb24uXHJcbiAqXHJcbiAqIEBwYXJhbSB7T2JqZWN0fSBsaXN0ZW5lciAtIFRoZSBsaXN0ZW5lciB0byBiZSByZW1vdmVkLlxyXG4gKi9cclxuZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXIpIHtcclxuICAgIGNvbnN0IGV2ZW50TmFtZSA9IGxpc3RlbmVyLmV2ZW50TmFtZTtcclxuICAgIGxldCBsaXN0ZW5lcnMgPSBldmVudExpc3RlbmVycy5nZXQoZXZlbnROYW1lKS5maWx0ZXIobCA9PiBsICE9PSBsaXN0ZW5lcik7XHJcbiAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkgZXZlbnRMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSk7XHJcbiAgICBlbHNlIGV2ZW50TGlzdGVuZXJzLnNldChldmVudE5hbWUsIGxpc3RlbmVycyk7XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogUmVtb3ZlcyBldmVudCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQgbmFtZXMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVtb3ZlIGxpc3RlbmVycyBmb3IuXHJcbiAqIEBwYXJhbSB7Li4uc3RyaW5nfSBhZGRpdGlvbmFsRXZlbnROYW1lcyAtIEFkZGl0aW9uYWwgZXZlbnQgbmFtZXMgdG8gcmVtb3ZlIGxpc3RlbmVycyBmb3IuXHJcbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBPZmYoZXZlbnROYW1lLCAuLi5hZGRpdGlvbmFsRXZlbnROYW1lcykge1xyXG4gICAgbGV0IGV2ZW50c1RvUmVtb3ZlID0gW2V2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXNdO1xyXG4gICAgZXZlbnRzVG9SZW1vdmUuZm9yRWFjaChldmVudE5hbWUgPT4gZXZlbnRMaXN0ZW5lcnMuZGVsZXRlKGV2ZW50TmFtZSkpO1xyXG59XHJcbi8qKlxyXG4gKiBSZW1vdmVzIGFsbCBldmVudCBsaXN0ZW5lcnMuXHJcbiAqXHJcbiAqIEBmdW5jdGlvbiBPZmZBbGxcclxuICogQHJldHVybnMge3ZvaWR9XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gT2ZmQWxsKCkgeyBldmVudExpc3RlbmVycy5jbGVhcigpOyB9XHJcblxyXG4vKipcclxuICogRW1pdHMgYW4gZXZlbnQgdXNpbmcgdGhlIGdpdmVuIGV2ZW50IG5hbWUuXHJcbiAqXHJcbiAqIEBwYXJhbSB7V2FpbHNFdmVudH0gZXZlbnQgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gZW1pdC5cclxuICogQHJldHVybnMge2FueX0gLSBUaGUgcmVzdWx0IG9mIHRoZSBlbWl0dGVkIGV2ZW50LlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEVtaXQoZXZlbnQpIHsgcmV0dXJuIGNhbGwoRW1pdE1ldGhvZCwgZXZlbnQpOyB9XHJcbiIsICJcbmV4cG9ydCBjb25zdCBFdmVudFR5cGVzID0ge1xuXHRXaW5kb3dzOiB7XG5cdFx0U3lzdGVtVGhlbWVDaGFuZ2VkOiBcIndpbmRvd3M6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdFx0QVBNUG93ZXJTdGF0dXNDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclN0YXR1c0NoYW5nZVwiLFxuXHRcdEFQTVN1c3BlbmQ6IFwid2luZG93czpBUE1TdXNwZW5kXCIsXG5cdFx0QVBNUmVzdW1lQXV0b21hdGljOiBcIndpbmRvd3M6QVBNUmVzdW1lQXV0b21hdGljXCIsXG5cdFx0QVBNUmVzdW1lU3VzcGVuZDogXCJ3aW5kb3dzOkFQTVJlc3VtZVN1c3BlbmRcIixcblx0XHRBUE1Qb3dlclNldHRpbmdDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclNldHRpbmdDaGFuZ2VcIixcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwid2luZG93czpBcHBsaWNhdGlvblN0YXJ0ZWRcIixcblx0XHRXZWJWaWV3TmF2aWdhdGlvbkNvbXBsZXRlZDogXCJ3aW5kb3dzOldlYlZpZXdOYXZpZ2F0aW9uQ29tcGxldGVkXCIsXG5cdFx0V2luZG93SW5hY3RpdmU6IFwid2luZG93czpXaW5kb3dJbmFjdGl2ZVwiLFxuXHRcdFdpbmRvd0FjdGl2ZTogXCJ3aW5kb3dzOldpbmRvd0FjdGl2ZVwiLFxuXHRcdFdpbmRvd0NsaWNrQWN0aXZlOiBcIndpbmRvd3M6V2luZG93Q2xpY2tBY3RpdmVcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcIndpbmRvd3M6V2luZG93RnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1VuRnVsbHNjcmVlbjogXCJ3aW5kb3dzOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwid2luZG93czpXaW5kb3dSZXN0b3JlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwid2luZG93czpXaW5kb3dNaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWluaW1pc2U6IFwid2luZG93czpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2U6IFwid2luZG93czpXaW5kb3dDbG9zZVwiLFxuXHRcdFdpbmRvd1NldEZvY3VzOiBcIndpbmRvd3M6V2luZG93U2V0Rm9jdXNcIixcblx0XHRXaW5kb3dLaWxsRm9jdXM6IFwid2luZG93czpXaW5kb3dLaWxsRm9jdXNcIixcblx0XHRXaW5kb3dEcmFnRHJvcDogXCJ3aW5kb3dzOldpbmRvd0RyYWdEcm9wXCIsXG5cdFx0V2luZG93RHJhZ0VudGVyOiBcIndpbmRvd3M6V2luZG93RHJhZ0VudGVyXCIsXG5cdFx0V2luZG93RHJhZ0xlYXZlOiBcIndpbmRvd3M6V2luZG93RHJhZ0xlYXZlXCIsXG5cdFx0V2luZG93RHJhZ092ZXI6IFwid2luZG93czpXaW5kb3dEcmFnT3ZlclwiLFxuXHR9LFxuXHRNYWM6IHtcblx0XHRBcHBsaWNhdGlvbkRpZEJlY29tZUFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUVmZmVjdGl2ZUFwcGVhcmFuY2VcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUljb246IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlSWNvblwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU2NyZWVuUGFyYW1ldGVyc1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uXCIsXG5cdFx0QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmc6IFwibWFjOkFwcGxpY2F0aW9uRGlkRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25EaWRIaWRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZEhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFJlc2lnbkFjdGl2ZU5vdGlmaWNhdGlvbjogXCJtYWM6QXBwbGljYXRpb25EaWRSZXNpZ25BY3RpdmVOb3RpZmljYXRpb25cIixcblx0XHRBcHBsaWNhdGlvbkRpZFVuaGlkZTogXCJtYWM6QXBwbGljYXRpb25EaWRVbmhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25EaWRVcGRhdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxCZWNvbWVBY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbEJlY29tZUFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEZpbmlzaExhdW5jaGluZzogXCJtYWM6QXBwbGljYXRpb25XaWxsRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsSGlkZTogXCJtYWM6QXBwbGljYXRpb25XaWxsSGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFJlc2lnbkFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVGVybWluYXRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxVbmhpZGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFVuaGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsVXBkYXRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZTogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZSFcIixcblx0XHRBcHBsaWNhdGlvblNob3VsZEhhbmRsZVJlb3BlbjogXCJtYWM6QXBwbGljYXRpb25TaG91bGRIYW5kbGVSZW9wZW4hXCIsXG5cdFx0V2luZG93RGlkQmVjb21lS2V5OiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dEaWRCZWNvbWVNYWluOiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVNYWluXCIsXG5cdFx0V2luZG93RGlkQmVnaW5TaGVldDogXCJtYWM6V2luZG93RGlkQmVnaW5TaGVldFwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUFscGhhOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VBbHBoYVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUJhY2tpbmdMb2NhdGlvbjogXCJtYWM6V2luZG93RGlkQ2hhbmdlQmFja2luZ0xvY2F0aW9uXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQmFja2luZ1Byb3BlcnRpZXM6IFwibWFjOldpbmRvd0RpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOldpbmRvd0RpZENoYW5nZU9jY2x1c2lvblN0YXRlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW46IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2U6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2VQcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5TcGFjZVByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTaGFyaW5nVHlwZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2hhcmluZ1R5cGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUaXRsZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVGl0bGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUb29sYmFyOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VUb29sYmFyXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd0RpZERlbWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dEaWRFbmRTaGVldDogXCJtYWM6V2luZG93RGlkRW5kU2hlZXRcIixcblx0XHRXaW5kb3dEaWRFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd0RpZEVudGVyRnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dEaWRFeGl0RnVsbFNjcmVlbjogXCJtYWM6V2luZG93RGlkRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEV4aXRWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd0RpZEV4cG9zZTogXCJtYWM6V2luZG93RGlkRXhwb3NlXCIsXG5cdFx0V2luZG93RGlkRm9jdXM6IFwibWFjOldpbmRvd0RpZEZvY3VzXCIsXG5cdFx0V2luZG93RGlkTWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJtYWM6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRPcmRlck9mZlNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd0RpZE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dEaWRSZXNpZ25LZXk6IFwibWFjOldpbmRvd0RpZFJlc2lnbktleVwiLFxuXHRcdFdpbmRvd0RpZFJlc2lnbk1haW46IFwibWFjOldpbmRvd0RpZFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwibWFjOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZTogXCJtYWM6V2luZG93RGlkVXBkYXRlXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd0RpZFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRpdGxlOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVRvb2xiYXJcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5XCIsXG5cdFx0V2luZG93U2hvdWxkQ2xvc2U6IFwibWFjOldpbmRvd1Nob3VsZENsb3NlIVwiLFxuXHRcdFdpbmRvd1dpbGxCZWNvbWVLZXk6IFwibWFjOldpbmRvd1dpbGxCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dXaWxsQmVjb21lTWFpbjogXCJtYWM6V2luZG93V2lsbEJlY29tZU1haW5cIixcblx0XHRXaW5kb3dXaWxsQmVnaW5TaGVldDogXCJtYWM6V2luZG93V2lsbEJlZ2luU2hlZXRcIixcblx0XHRXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93V2lsbENsb3NlOiBcIm1hYzpXaW5kb3dXaWxsQ2xvc2VcIixcblx0XHRXaW5kb3dXaWxsRGVtaW5pYXR1cml6ZTogXCJtYWM6V2luZG93V2lsbERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd1dpbGxFbnRlclZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEV4aXRGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyOiBcIm1hYzpXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsRm9jdXNcIixcblx0XHRXaW5kb3dXaWxsTWluaWF0dXJpemU6IFwibWFjOldpbmRvd1dpbGxNaW5pYXR1cml6ZVwiLFxuXHRcdFdpbmRvd1dpbGxNb3ZlOiBcIm1hYzpXaW5kb3dXaWxsTW92ZVwiLFxuXHRcdFdpbmRvd1dpbGxPcmRlck9mZlNjcmVlbjogXCJtYWM6V2luZG93V2lsbE9yZGVyT2ZmU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd1dpbGxPcmRlck9uU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbFJlc2lnbk1haW46IFwibWFjOldpbmRvd1dpbGxSZXNpZ25NYWluXCIsXG5cdFx0V2luZG93V2lsbFJlc2l6ZTogXCJtYWM6V2luZG93V2lsbFJlc2l6ZVwiLFxuXHRcdFdpbmRvd1dpbGxVbmZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsVW5mb2N1c1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVBbHBoYVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3I6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXM6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllc1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVTaGFkb3dcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlVGl0bGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVUb29sYmFyOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVG9vbGJhclwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd1dpbGxVc2VTdGFuZGFyZEZyYW1lOiBcIm1hYzpXaW5kb3dXaWxsVXNlU3RhbmRhcmRGcmFtZVwiLFxuXHRcdE1lbnVXaWxsT3BlbjogXCJtYWM6TWVudVdpbGxPcGVuXCIsXG5cdFx0TWVudURpZE9wZW46IFwibWFjOk1lbnVEaWRPcGVuXCIsXG5cdFx0TWVudURpZENsb3NlOiBcIm1hYzpNZW51RGlkQ2xvc2VcIixcblx0XHRNZW51V2lsbFNlbmRBY3Rpb246IFwibWFjOk1lbnVXaWxsU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVXaWxsSGlnaGxpZ2h0SXRlbTogXCJtYWM6TWVudVdpbGxIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudURpZEhpZ2hsaWdodEl0ZW06IFwibWFjOk1lbnVEaWRIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudVdpbGxEaXNwbGF5SXRlbTogXCJtYWM6TWVudVdpbGxEaXNwbGF5SXRlbVwiLFxuXHRcdE1lbnVEaWREaXNwbGF5SXRlbTogXCJtYWM6TWVudURpZERpc3BsYXlJdGVtXCIsXG5cdFx0TWVudVdpbGxBZGRJdGVtOiBcIm1hYzpNZW51V2lsbEFkZEl0ZW1cIixcblx0XHRNZW51RGlkQWRkSXRlbTogXCJtYWM6TWVudURpZEFkZEl0ZW1cIixcblx0XHRNZW51V2lsbFJlbW92ZUl0ZW06IFwibWFjOk1lbnVXaWxsUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVEaWRSZW1vdmVJdGVtOiBcIm1hYzpNZW51RGlkUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVXaWxsQmVnaW5UcmFja2luZzogXCJtYWM6TWVudVdpbGxCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudURpZEJlZ2luVHJhY2tpbmc6IFwibWFjOk1lbnVEaWRCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxFbmRUcmFja2luZzogXCJtYWM6TWVudVdpbGxFbmRUcmFja2luZ1wiLFxuXHRcdE1lbnVEaWRFbmRUcmFja2luZzogXCJtYWM6TWVudURpZEVuZFRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxVcGRhdGU6IFwibWFjOk1lbnVXaWxsVXBkYXRlXCIsXG5cdFx0TWVudURpZFVwZGF0ZTogXCJtYWM6TWVudURpZFVwZGF0ZVwiLFxuXHRcdE1lbnVXaWxsUG9wVXA6IFwibWFjOk1lbnVXaWxsUG9wVXBcIixcblx0XHRNZW51RGlkUG9wVXA6IFwibWFjOk1lbnVEaWRQb3BVcFwiLFxuXHRcdE1lbnVXaWxsU2VuZEFjdGlvblRvSXRlbTogXCJtYWM6TWVudVdpbGxTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0TWVudURpZFNlbmRBY3Rpb25Ub0l0ZW06IFwibWFjOk1lbnVEaWRTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0V2ViVmlld0RpZFN0YXJ0UHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkU3RhcnRQcm92aXNpb25hbE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZENvbW1pdE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRDb21taXROYXZpZ2F0aW9uXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZFwiLFxuXHRcdFdpbmRvd0ZpbGVEcmFnZ2luZ1BlcmZvcm1lZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nUGVyZm9ybWVkXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRXhpdGVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdFeGl0ZWRcIixcblx0fSxcblx0TGludXg6IHtcblx0XHRTeXN0ZW1UaGVtZUNoYW5nZWQ6IFwibGludXg6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdH0sXG5cdENvbW1vbjoge1xuXHRcdEFwcGxpY2F0aW9uU3RhcnRlZDogXCJjb21tb246QXBwbGljYXRpb25TdGFydGVkXCIsXG5cdFx0V2luZG93TWF4aW1pc2U6IFwiY29tbW9uOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJjb21tb246V2luZG93VW5NYXhpbWlzZVwiLFxuXHRcdFdpbmRvd0Z1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd0Z1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dVbkZ1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwiY29tbW9uOldpbmRvd1Jlc3RvcmVcIixcblx0XHRXaW5kb3dNaW5pbWlzZTogXCJjb21tb246V2luZG93TWluaW1pc2VcIixcblx0XHRXaW5kb3dVbk1pbmltaXNlOiBcImNvbW1vbjpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2luZzogXCJjb21tb246V2luZG93Q2xvc2luZ1wiLFxuXHRcdFdpbmRvd1pvb206IFwiY29tbW9uOldpbmRvd1pvb21cIixcblx0XHRXaW5kb3dab29tSW46IFwiY29tbW9uOldpbmRvd1pvb21JblwiLFxuXHRcdFdpbmRvd1pvb21PdXQ6IFwiY29tbW9uOldpbmRvd1pvb21PdXRcIixcblx0XHRXaW5kb3dab29tUmVzZXQ6IFwiY29tbW9uOldpbmRvd1pvb21SZXNldFwiLFxuXHRcdFdpbmRvd0ZvY3VzOiBcImNvbW1vbjpXaW5kb3dGb2N1c1wiLFxuXHRcdFdpbmRvd0xvc3RGb2N1czogXCJjb21tb246V2luZG93TG9zdEZvY3VzXCIsXG5cdFx0V2luZG93U2hvdzogXCJjb21tb246V2luZG93U2hvd1wiLFxuXHRcdFdpbmRvd0hpZGU6IFwiY29tbW9uOldpbmRvd0hpZGVcIixcblx0XHRXaW5kb3dEUElDaGFuZ2VkOiBcImNvbW1vbjpXaW5kb3dEUElDaGFuZ2VkXCIsXG5cdFx0V2luZG93RmlsZXNEcm9wcGVkOiBcImNvbW1vbjpXaW5kb3dGaWxlc0Ryb3BwZWRcIixcblx0XHRXaW5kb3dSdW50aW1lUmVhZHk6IFwiY29tbW9uOldpbmRvd1J1bnRpbWVSZWFkeVwiLFxuXHRcdFRoZW1lQ2hhbmdlZDogXCJjb21tb246VGhlbWVDaGFuZ2VkXCIsXG5cdH0sXG59O1xuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBPcGVuRmlsZURpYWxvZ09wdGlvbnNcclxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ2hvb3NlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjaG9zZW4uXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZUZpbGVzXSAtIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DcmVhdGVEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNyZWF0ZWQuXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1Nob3dIaWRkZW5GaWxlc10gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGZpbGVzIHNob3VsZCBiZSBzaG93bi5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbUmVzb2x2ZXNBbGlhc2VzXSAtIEluZGljYXRlcyBpZiBhbGlhc2VzIHNob3VsZCBiZSByZXNvbHZlZC5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbQWxsb3dzTXVsdGlwbGVTZWxlY3Rpb25dIC0gSW5kaWNhdGVzIGlmIG11bHRpcGxlIHNlbGVjdGlvbiBpcyBhbGxvd2VkLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtIaWRlRXh0ZW5zaW9uXSAtIEluZGljYXRlcyBpZiB0aGUgZXh0ZW5zaW9uIHNob3VsZCBiZSBoaWRkZW4uXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhblNlbGVjdEhpZGRlbkV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGV4dGVuc2lvbnMgY2FuIGJlIHNlbGVjdGVkLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtUcmVhdHNGaWxlUGFja2FnZXNBc0RpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBmaWxlIHBhY2thZ2VzIHNob3VsZCBiZSB0cmVhdGVkIGFzIGRpcmVjdG9yaWVzLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtBbGxvd3NPdGhlckZpbGV0eXBlc10gLSBJbmRpY2F0ZXMgaWYgb3RoZXIgZmlsZSB0eXBlcyBhcmUgYWxsb3dlZC5cclxuICogQHByb3BlcnR5IHtGaWxlRmlsdGVyW119IFtGaWx0ZXJzXSAtIEFycmF5IG9mIGZpbGUgZmlsdGVycy5cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtUaXRsZV0gLSBUaXRsZSBvZiB0aGUgZGlhbG9nLlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW01lc3NhZ2VdIC0gTWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbQnV0dG9uVGV4dF0gLSBUZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi5cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtEaXJlY3RvcnldIC0gRGlyZWN0b3J5IHRvIG9wZW4gaW4gdGhlIGRpYWxvZy5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbRGV0YWNoZWRdIC0gSW5kaWNhdGVzIGlmIHRoZSBkaWFsb2cgc2hvdWxkIGFwcGVhciBkZXRhY2hlZCBmcm9tIHRoZSBtYWluIHdpbmRvdy5cclxuICovXHJcblxyXG5cclxuLyoqXHJcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNhdmVGaWxlRGlhbG9nT3B0aW9uc1xyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0ZpbGVuYW1lXSAtIERlZmF1bHQgZmlsZW5hbWUgdG8gdXNlIGluIHRoZSBkaWFsb2cuXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZURpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBkaXJlY3RvcmllcyBjYW4gYmUgY2hvc2VuLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DaG9vc2VGaWxlc10gLSBJbmRpY2F0ZXMgaWYgZmlsZXMgY2FuIGJlIGNob3Nlbi5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ3JlYXRlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtTaG93SGlkZGVuRmlsZXNdIC0gSW5kaWNhdGVzIGlmIGhpZGRlbiBmaWxlcyBzaG91bGQgYmUgc2hvd24uXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1Jlc29sdmVzQWxpYXNlc10gLSBJbmRpY2F0ZXMgaWYgYWxpYXNlcyBzaG91bGQgYmUgcmVzb2x2ZWQuXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c011bHRpcGxlU2VsZWN0aW9uXSAtIEluZGljYXRlcyBpZiBtdWx0aXBsZSBzZWxlY3Rpb24gaXMgYWxsb3dlZC5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbSGlkZUV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgdGhlIGV4dGVuc2lvbiBzaG91bGQgYmUgaGlkZGVuLlxyXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5TZWxlY3RIaWRkZW5FeHRlbnNpb25dIC0gSW5kaWNhdGVzIGlmIGhpZGRlbiBleHRlbnNpb25zIGNhbiBiZSBzZWxlY3RlZC5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZmlsZSBwYWNrYWdlcyBzaG91bGQgYmUgdHJlYXRlZCBhcyBkaXJlY3Rvcmllcy5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbQWxsb3dzT3RoZXJGaWxldHlwZXNdIC0gSW5kaWNhdGVzIGlmIG90aGVyIGZpbGUgdHlwZXMgYXJlIGFsbG93ZWQuXHJcbiAqIEBwcm9wZXJ0eSB7RmlsZUZpbHRlcltdfSBbRmlsdGVyc10gLSBBcnJheSBvZiBmaWxlIGZpbHRlcnMuXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGl0bGUgb2YgdGhlIGRpYWxvZy5cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtNZXNzYWdlXSAtIE1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0J1dHRvblRleHRdIC0gVGV4dCB0byBkaXNwbGF5IG9uIHRoZSBidXR0b24uXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRGlyZWN0b3J5XSAtIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuXHJcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0RldGFjaGVkXSAtIEluZGljYXRlcyBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cuXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE1lc3NhZ2VEaWFsb2dPcHRpb25zXHJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGhlIHRpdGxlIG9mIHRoZSBkaWFsb2cgd2luZG93LlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW01lc3NhZ2VdIC0gVGhlIG1haW4gbWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuXHJcbiAqIEBwcm9wZXJ0eSB7QnV0dG9uW119IFtCdXR0b25zXSAtIEFycmF5IG9mIGJ1dHRvbiBvcHRpb25zIHRvIHNob3cgaW4gdGhlIGRpYWxvZy5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbRGV0YWNoZWRdIC0gVHJ1ZSBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cgKGlmIGFwcGxpY2FibGUpLlxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBCdXR0b25cclxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtMYWJlbF0gLSBUZXh0IHRoYXQgYXBwZWFycyB3aXRoaW4gdGhlIGJ1dHRvbi5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbSXNDYW5jZWxdIC0gVHJ1ZSBpZiB0aGUgYnV0dG9uIHNob3VsZCBjYW5jZWwgYW4gb3BlcmF0aW9uIHdoZW4gY2xpY2tlZC5cclxuICogQHByb3BlcnR5IHtib29sZWFufSBbSXNEZWZhdWx0XSAtIFRydWUgaWYgdGhlIGJ1dHRvbiBzaG91bGQgYmUgdGhlIGRlZmF1bHQgYWN0aW9uIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyBlbnRlci5cclxuICovXHJcblxyXG4vKipcclxuICogQHR5cGVkZWYge09iamVjdH0gRmlsZUZpbHRlclxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0Rpc3BsYXlOYW1lXSAtIERpc3BsYXkgbmFtZSBmb3IgdGhlIGZpbHRlciwgaXQgY291bGQgYmUgXCJUZXh0IEZpbGVzXCIsIFwiSW1hZ2VzXCIgZXRjLlxyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW1BhdHRlcm5dIC0gUGF0dGVybiB0byBtYXRjaCBmb3IgdGhlIGZpbHRlciwgZS5nLiBcIioudHh0OyoubWRcIiBmb3IgdGV4dCBtYXJrZG93biBmaWxlcy5cclxuICovXHJcblxyXG4vLyBzZXR1cFxyXG53aW5kb3cuX3dhaWxzID0gd2luZG93Ll93YWlscyB8fCB7fTtcclxud2luZG93Ll93YWlscy5kaWFsb2dFcnJvckNhbGxiYWNrID0gZGlhbG9nRXJyb3JDYWxsYmFjaztcclxud2luZG93Ll93YWlscy5kaWFsb2dSZXN1bHRDYWxsYmFjayA9IGRpYWxvZ1Jlc3VsdENhbGxiYWNrO1xyXG5cclxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xyXG5cclxuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSAnbmFub2lkL25vbi1zZWN1cmUnO1xyXG5cclxuLy8gRGVmaW5lIGNvbnN0YW50cyBmcm9tIHRoZSBgbWV0aG9kc2Agb2JqZWN0IGluIFRpdGxlIENhc2VcclxuY29uc3QgRGlhbG9nSW5mbyA9IDA7XHJcbmNvbnN0IERpYWxvZ1dhcm5pbmcgPSAxO1xyXG5jb25zdCBEaWFsb2dFcnJvciA9IDI7XHJcbmNvbnN0IERpYWxvZ1F1ZXN0aW9uID0gMztcclxuY29uc3QgRGlhbG9nT3BlbkZpbGUgPSA0O1xyXG5jb25zdCBEaWFsb2dTYXZlRmlsZSA9IDU7XHJcblxyXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5EaWFsb2csICcnKTtcclxuY29uc3QgZGlhbG9nUmVzcG9uc2VzID0gbmV3IE1hcCgpO1xyXG5cclxuLyoqXHJcbiAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBpZCB0aGF0IGlzIG5vdCBwcmVzZW50IGluIGRpYWxvZ1Jlc3BvbnNlcy5cclxuICogQHJldHVybnMge3N0cmluZ30gdW5pcXVlIGlkXHJcbiAqL1xyXG5mdW5jdGlvbiBnZW5lcmF0ZUlEKCkge1xyXG4gICAgbGV0IHJlc3VsdDtcclxuICAgIGRvIHtcclxuICAgICAgICByZXN1bHQgPSBuYW5vaWQoKTtcclxuICAgIH0gd2hpbGUgKGRpYWxvZ1Jlc3BvbnNlcy5oYXMocmVzdWx0KSk7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG4vKipcclxuICogU2hvd3MgYSBkaWFsb2cgb2Ygc3BlY2lmaWVkIHR5cGUgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy5cclxuICogQHBhcmFtIHtudW1iZXJ9IHR5cGUgLSB0eXBlIG9mIGRpYWxvZ1xyXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfE9wZW5GaWxlRGlhbG9nT3B0aW9uc3xTYXZlRmlsZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBvcHRpb25zIGZvciB0aGUgZGlhbG9nXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlfSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCByZXN1bHQgb2YgZGlhbG9nXHJcbiAqL1xyXG5mdW5jdGlvbiBkaWFsb2codHlwZSwgb3B0aW9ucyA9IHt9KSB7XHJcbiAgICBjb25zdCBpZCA9IGdlbmVyYXRlSUQoKTtcclxuICAgIG9wdGlvbnNbXCJkaWFsb2ctaWRcIl0gPSBpZDtcclxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgZGlhbG9nUmVzcG9uc2VzLnNldChpZCwge3Jlc29sdmUsIHJlamVjdH0pO1xyXG4gICAgICAgIGNhbGwodHlwZSwgb3B0aW9ucykuY2F0Y2goKGVycm9yKSA9PiB7XHJcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XHJcbiAgICAgICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5kZWxldGUoaWQpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBIYW5kbGVzIHRoZSBjYWxsYmFjayBmcm9tIGEgZGlhbG9nLlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBUaGUgSUQgb2YgdGhlIGRpYWxvZyByZXNwb25zZS5cclxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgLSBUaGUgZGF0YSByZWNlaXZlZCBmcm9tIHRoZSBkaWFsb2cuXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNKU09OIC0gRmxhZyBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIGRhdGEgaXMgaW4gSlNPTiBmb3JtYXQuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cclxuICovXHJcbmZ1bmN0aW9uIGRpYWxvZ1Jlc3VsdENhbGxiYWNrKGlkLCBkYXRhLCBpc0pTT04pIHtcclxuICAgIGxldCBwID0gZGlhbG9nUmVzcG9uc2VzLmdldChpZCk7XHJcbiAgICBpZiAocCkge1xyXG4gICAgICAgIGlmIChpc0pTT04pIHtcclxuICAgICAgICAgICAgcC5yZXNvbHZlKEpTT04ucGFyc2UoZGF0YSkpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHAucmVzb2x2ZShkYXRhKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZGlhbG9nUmVzcG9uc2VzLmRlbGV0ZShpZCk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDYWxsYmFjayBmdW5jdGlvbiBmb3IgaGFuZGxpbmcgZXJyb3JzIGluIGRpYWxvZy5cclxuICpcclxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSBkaWFsb2cgcmVzcG9uc2UuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3ZvaWR9XHJcbiAqL1xyXG5mdW5jdGlvbiBkaWFsb2dFcnJvckNhbGxiYWNrKGlkLCBtZXNzYWdlKSB7XHJcbiAgICBsZXQgcCA9IGRpYWxvZ1Jlc3BvbnNlcy5nZXQoaWQpO1xyXG4gICAgaWYgKHApIHtcclxuICAgICAgICBwLnJlamVjdChtZXNzYWdlKTtcclxuICAgICAgICBkaWFsb2dSZXNwb25zZXMuZGVsZXRlKGlkKTtcclxuICAgIH1cclxufVxyXG5cclxuXHJcbi8vIFJlcGxhY2UgYG1ldGhvZHNgIHdpdGggY29uc3RhbnRzIGluIFRpdGxlIENhc2VcclxuXHJcbi8qKlxyXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcclxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gLSBUaGUgbGFiZWwgb2YgdGhlIGJ1dHRvbiBwcmVzc2VkXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgSW5mbyA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nSW5mbywgb3B0aW9ucyk7XHJcblxyXG4vKipcclxuICogQHBhcmFtIHtNZXNzYWdlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gVGhlIGxhYmVsIG9mIHRoZSBidXR0b24gcHJlc3NlZFxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IFdhcm5pbmcgPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ1dhcm5pbmcsIG9wdGlvbnMpO1xyXG5cclxuLyoqXHJcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcclxuICovXHJcbmV4cG9ydCBjb25zdCBFcnJvciA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nRXJyb3IsIG9wdGlvbnMpO1xyXG5cclxuLyoqXHJcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xyXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcclxuICovXHJcbmV4cG9ydCBjb25zdCBRdWVzdGlvbiA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nUXVlc3Rpb24sIG9wdGlvbnMpO1xyXG5cclxuLyoqXHJcbiAqIEBwYXJhbSB7T3BlbkZpbGVEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcclxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nW118c3RyaW5nPn0gUmV0dXJucyBzZWxlY3RlZCBmaWxlIG9yIGxpc3Qgb2YgZmlsZXMuIFJldHVybnMgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaXMgc2VsZWN0ZWQuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgT3BlbkZpbGUgPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ09wZW5GaWxlLCBvcHRpb25zKTtcclxuXHJcbi8qKlxyXG4gKiBAcGFyYW0ge1NhdmVGaWxlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IFJldHVybnMgdGhlIHNlbGVjdGVkIGZpbGUuIFJldHVybnMgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaXMgc2VsZWN0ZWQuXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgU2F2ZUZpbGUgPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ1NhdmVGaWxlLCBvcHRpb25zKTtcclxuIiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuaW1wb3J0IHsgbmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXMgfSBmcm9tIFwiLi9ydW50aW1lXCI7XHJcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZC9ub24tc2VjdXJlJztcclxuXHJcbi8vIFNldHVwXHJcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xyXG53aW5kb3cuX3dhaWxzLmNhbGxSZXN1bHRIYW5kbGVyID0gcmVzdWx0SGFuZGxlcjtcclxud2luZG93Ll93YWlscy5jYWxsRXJyb3JIYW5kbGVyID0gZXJyb3JIYW5kbGVyO1xyXG5cclxuXHJcbmNvbnN0IENhbGxCaW5kaW5nID0gMDtcclxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ2FsbCwgJycpO1xyXG5sZXQgY2FsbFJlc3BvbnNlcyA9IG5ldyBNYXAoKTtcclxuXHJcbi8qKlxyXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgSUQgdXNpbmcgdGhlIG5hbm9pZCBsaWJyYXJ5LlxyXG4gKlxyXG4gKiBAcmV0dXJuIHtzdHJpbmd9IC0gQSB1bmlxdWUgSUQgdGhhdCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgY2FsbFJlc3BvbnNlcyBzZXQuXHJcbiAqL1xyXG5mdW5jdGlvbiBnZW5lcmF0ZUlEKCkge1xyXG4gICAgbGV0IHJlc3VsdDtcclxuICAgIGRvIHtcclxuICAgICAgICByZXN1bHQgPSBuYW5vaWQoKTtcclxuICAgIH0gd2hpbGUgKGNhbGxSZXNwb25zZXMuaGFzKHJlc3VsdCkpO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuLyoqXHJcbiAqIEhhbmRsZXMgdGhlIHJlc3VsdCBvZiBhIGNhbGwgcmVxdWVzdC5cclxuICpcclxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSByZXF1ZXN0IHRvIGhhbmRsZSB0aGUgcmVzdWx0IGZvci5cclxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgLSBUaGUgcmVzdWx0IGRhdGEgb2YgdGhlIHJlcXVlc3QuXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNKU09OIC0gSW5kaWNhdGVzIHdoZXRoZXIgdGhlIGRhdGEgaXMgSlNPTiBvciBub3QuXHJcbiAqXHJcbiAqIEByZXR1cm4ge3VuZGVmaW5lZH0gLSBUaGlzIG1ldGhvZCBkb2VzIG5vdCByZXR1cm4gYW55IHZhbHVlLlxyXG4gKi9cclxuZnVuY3Rpb24gcmVzdWx0SGFuZGxlcihpZCwgZGF0YSwgaXNKU09OKSB7XHJcbiAgICBjb25zdCBwcm9taXNlSGFuZGxlciA9IGdldEFuZERlbGV0ZVJlc3BvbnNlKGlkKTtcclxuICAgIGlmIChwcm9taXNlSGFuZGxlcikge1xyXG4gICAgICAgIHByb21pc2VIYW5kbGVyLnJlc29sdmUoaXNKU09OID8gSlNPTi5wYXJzZShkYXRhKSA6IGRhdGEpO1xyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogSGFuZGxlcyB0aGUgZXJyb3IgZnJvbSBhIGNhbGwgcmVxdWVzdC5cclxuICpcclxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSBwcm9taXNlIGhhbmRsZXIuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UgdG8gcmVqZWN0IHRoZSBwcm9taXNlIGhhbmRsZXIgd2l0aC5cclxuICpcclxuICogQHJldHVybiB7dm9pZH1cclxuICovXHJcbmZ1bmN0aW9uIGVycm9ySGFuZGxlcihpZCwgbWVzc2FnZSkge1xyXG4gICAgY29uc3QgcHJvbWlzZUhhbmRsZXIgPSBnZXRBbmREZWxldGVSZXNwb25zZShpZCk7XHJcbiAgICBpZiAocHJvbWlzZUhhbmRsZXIpIHtcclxuICAgICAgICBwcm9taXNlSGFuZGxlci5yZWplY3QobWVzc2FnZSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXRyaWV2ZXMgYW5kIHJlbW92ZXMgdGhlIHJlc3BvbnNlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gSUQgZnJvbSB0aGUgY2FsbFJlc3BvbnNlcyBtYXAuXHJcbiAqXHJcbiAqIEBwYXJhbSB7YW55fSBpZCAtIFRoZSBJRCBvZiB0aGUgcmVzcG9uc2UgdG8gYmUgcmV0cmlldmVkIGFuZCByZW1vdmVkLlxyXG4gKlxyXG4gKiBAcmV0dXJucyB7YW55fSBUaGUgcmVzcG9uc2Ugb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gSUQuXHJcbiAqL1xyXG5mdW5jdGlvbiBnZXRBbmREZWxldGVSZXNwb25zZShpZCkge1xyXG4gICAgY29uc3QgcmVzcG9uc2UgPSBjYWxsUmVzcG9uc2VzLmdldChpZCk7XHJcbiAgICBjYWxsUmVzcG9uc2VzLmRlbGV0ZShpZCk7XHJcbiAgICByZXR1cm4gcmVzcG9uc2U7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFeGVjdXRlcyBhIGNhbGwgdXNpbmcgdGhlIHByb3ZpZGVkIHR5cGUgYW5kIG9wdGlvbnMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gdHlwZSAtIFRoZSB0eXBlIG9mIGNhbGwgdG8gZXhlY3V0ZS5cclxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSAtIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIGNhbGwuXHJcbiAqIEByZXR1cm4ge1Byb21pc2V9IC0gQSBwcm9taXNlIHRoYXQgd2lsbCBiZSByZXNvbHZlZCBvciByZWplY3RlZCBiYXNlZCBvbiB0aGUgcmVzdWx0IG9mIHRoZSBjYWxsLlxyXG4gKi9cclxuZnVuY3Rpb24gY2FsbEJpbmRpbmcodHlwZSwgb3B0aW9ucyA9IHt9KSB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IGlkID0gZ2VuZXJhdGVJRCgpO1xyXG4gICAgICAgIG9wdGlvbnNbXCJjYWxsLWlkXCJdID0gaWQ7XHJcbiAgICAgICAgY2FsbFJlc3BvbnNlcy5zZXQoaWQsIHsgcmVzb2x2ZSwgcmVqZWN0IH0pO1xyXG4gICAgICAgIGNhbGwodHlwZSwgb3B0aW9ucykuY2F0Y2goKGVycm9yKSA9PiB7XHJcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XHJcbiAgICAgICAgICAgIGNhbGxSZXNwb25zZXMuZGVsZXRlKGlkKTtcclxuICAgICAgICB9KTtcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogQ2FsbCBtZXRob2QuXHJcbiAqXHJcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgZm9yIHRoZSBtZXRob2QuXHJcbiAqIEByZXR1cm5zIHtPYmplY3R9IC0gVGhlIHJlc3VsdCBvZiB0aGUgY2FsbC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBDYWxsKG9wdGlvbnMpIHtcclxuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywgb3B0aW9ucyk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFeGVjdXRlcyBhIG1ldGhvZCBieSBuYW1lLlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgaW4gdGhlIGZvcm1hdCAncGFja2FnZS5zdHJ1Y3QubWV0aG9kJy5cclxuICogQHBhcmFtIHsuLi4qfSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXHJcbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgbmFtZSBpcyBub3QgYSBzdHJpbmcgb3IgaXMgbm90IGluIHRoZSBjb3JyZWN0IGZvcm1hdC5cclxuICogQHJldHVybnMgeyp9IFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBleGVjdXRpb24uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gQnlOYW1lKG5hbWUsIC4uLmFyZ3MpIHtcclxuICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gXCJzdHJpbmdcIiB8fCBuYW1lLnNwbGl0KFwiLlwiKS5sZW5ndGggIT09IDMpIHtcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYWxsQnlOYW1lIHJlcXVpcmVzIGEgc3RyaW5nIGluIHRoZSBmb3JtYXQgJ3BhY2thZ2Uuc3RydWN0Lm1ldGhvZCdcIik7XHJcbiAgICB9XHJcbiAgICBsZXQgW3BhY2thZ2VOYW1lLCBzdHJ1Y3ROYW1lLCBtZXRob2ROYW1lXSA9IG5hbWUuc3BsaXQoXCIuXCIpO1xyXG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XHJcbiAgICAgICAgcGFja2FnZU5hbWUsXHJcbiAgICAgICAgc3RydWN0TmFtZSxcclxuICAgICAgICBtZXRob2ROYW1lLFxyXG4gICAgICAgIGFyZ3NcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogQ2FsbHMgYSBtZXRob2QgYnkgaXRzIElEIHdpdGggdGhlIHNwZWNpZmllZCBhcmd1bWVudHMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBtZXRob2RJRCAtIFRoZSBJRCBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXHJcbiAqIEBwYXJhbSB7Li4uKn0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxyXG4gKiBAcmV0dXJuIHsqfSAtIFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBjYWxsLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEJ5SUQobWV0aG9kSUQsIC4uLmFyZ3MpIHtcclxuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywge1xyXG4gICAgICAgIG1ldGhvZElELFxyXG4gICAgICAgIGFyZ3NcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogQ2FsbHMgYSBtZXRob2Qgb24gYSBwbHVnaW4uXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBwbHVnaW5OYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHBsdWdpbi5cclxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXHJcbiAqIEBwYXJhbSB7Li4uKn0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxyXG4gKiBAcmV0dXJucyB7Kn0gLSBUaGUgcmVzdWx0IG9mIHRoZSBtZXRob2QgY2FsbC5cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBQbHVnaW4ocGx1Z2luTmFtZSwgbWV0aG9kTmFtZSwgLi4uYXJncykge1xyXG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XHJcbiAgICAgICAgcGFja2FnZU5hbWU6IFwid2FpbHMtcGx1Z2luc1wiLFxyXG4gICAgICAgIHN0cnVjdE5hbWU6IHBsdWdpbk5hbWUsXHJcbiAgICAgICAgbWV0aG9kTmFtZSxcclxuICAgICAgICBhcmdzXHJcbiAgICB9KTtcclxufVxyXG4iLCAiLypcclxuIF9cdCAgIF9fXHQgIF8gX19cclxufCB8XHQgLyAvX19fIF8oXykgL19fX19cclxufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xyXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcclxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXHJcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cclxuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxyXG4qL1xyXG5cclxuaW1wb3J0IHtkZWJ1Z0xvZ30gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZ1wiO1xyXG5cclxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XHJcblxyXG5pbXBvcnQgKiBhcyBBcHBsaWNhdGlvbiBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb25cIjtcclxuaW1wb3J0ICogYXMgQnJvd3NlciBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvYnJvd3NlclwiO1xyXG5pbXBvcnQgKiBhcyBDbGlwYm9hcmQgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZFwiO1xyXG5pbXBvcnQgKiBhcyBGbGFncyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3NcIjtcclxuaW1wb3J0ICogYXMgU2NyZWVucyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvc2NyZWVuc1wiO1xyXG5pbXBvcnQgKiBhcyBTeXN0ZW0gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbVwiO1xyXG5pbXBvcnQgKiBhcyBXaW5kb3cgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dpbmRvd1wiO1xyXG5pbXBvcnQgKiBhcyBXTUwgZnJvbSAnLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvd21sJztcclxuaW1wb3J0ICogYXMgRXZlbnRzIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9ldmVudHNcIjtcclxuaW1wb3J0ICogYXMgRGlhbG9ncyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZGlhbG9nc1wiO1xyXG5pbXBvcnQgKiBhcyBDYWxsIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxsc1wiO1xyXG5pbXBvcnQge2ludm9rZX0gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbVwiO1xyXG5cclxuLyoqKlxyXG4gVGhpcyB0ZWNobmlxdWUgZm9yIHByb3BlciBsb2FkIGRldGVjdGlvbiBpcyB0YWtlbiBmcm9tIEhUTVg6XHJcblxyXG4gQlNEIDItQ2xhdXNlIExpY2Vuc2VcclxuXHJcbiBDb3B5cmlnaHQgKGMpIDIwMjAsIEJpZyBTa3kgU29mdHdhcmVcclxuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcblxyXG4gUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0XHJcbiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcclxuXHJcbiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcclxuIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxyXG5cclxuIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcclxuIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cclxuIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxyXG5cclxuIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiXHJcbiBBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFXHJcbiBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcclxuIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEVcclxuIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMXHJcbiBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUlxyXG4gU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVJcclxuIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksXHJcbiBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRVxyXG4gT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cclxuXHJcbiAqKiovXHJcblxyXG53aW5kb3cuX3dhaWxzLmludm9rZT1pbnZva2U7XHJcblxyXG53aW5kb3cud2FpbHMgPSB3aW5kb3cud2FpbHMgfHwge307XHJcbndpbmRvdy53YWlscy5BcHBsaWNhdGlvbiA9IEFwcGxpY2F0aW9uO1xyXG53aW5kb3cud2FpbHMuQnJvd3NlciA9IEJyb3dzZXI7XHJcbndpbmRvdy53YWlscy5DYWxsID0gQ2FsbDtcclxud2luZG93LndhaWxzLkNsaXBib2FyZCA9IENsaXBib2FyZDtcclxud2luZG93LndhaWxzLkRpYWxvZ3MgPSBEaWFsb2dzO1xyXG53aW5kb3cud2FpbHMuRXZlbnRzID0gRXZlbnRzO1xyXG53aW5kb3cud2FpbHMuRmxhZ3MgPSBGbGFncztcclxud2luZG93LndhaWxzLlNjcmVlbnMgPSBTY3JlZW5zO1xyXG53aW5kb3cud2FpbHMuU3lzdGVtID0gU3lzdGVtO1xyXG53aW5kb3cud2FpbHMuV2luZG93ID0gV2luZG93O1xyXG53aW5kb3cud2FpbHMuV01MID0gV01MO1xyXG5cclxuXHJcbmxldCBpc1JlYWR5ID0gZmFsc2VcclxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGZ1bmN0aW9uKCkge1xyXG4gICAgaXNSZWFkeSA9IHRydWVcclxuICAgIHdpbmRvdy5fd2FpbHMuaW52b2tlKCd3YWlsczpydW50aW1lOnJlYWR5Jyk7XHJcbiAgICBpZihERUJVRykge1xyXG4gICAgICAgIGRlYnVnTG9nKFwiV2FpbHMgUnVudGltZSBMb2FkZWRcIik7XHJcbiAgICB9XHJcbn0pXHJcblxyXG5mdW5jdGlvbiB3aGVuUmVhZHkoZm4pIHtcclxuICAgIGlmIChpc1JlYWR5IHx8IGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdjb21wbGV0ZScpIHtcclxuICAgICAgICBmbigpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZm4pO1xyXG4gICAgfVxyXG59XHJcblxyXG53aGVuUmVhZHkoKCkgPT4ge1xyXG4gICAgV01MLlJlbG9hZCgpO1xyXG59KTtcclxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7QUFLTyxXQUFTLFNBQVMsU0FBUztBQUU5QixZQUFRO0FBQUEsTUFDSixrQkFBa0IsVUFBVTtBQUFBLE1BQzVCO0FBQUEsTUFDQTtBQUFBLElBQ0o7QUFBQSxFQUNKOzs7QUNaQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7OztBQ0FBLE1BQUksY0FDRjtBQVdLLE1BQUksU0FBUyxDQUFDQSxRQUFPLE9BQU87QUFDakMsUUFBSSxLQUFLO0FBQ1QsUUFBSSxJQUFJQTtBQUNSLFdBQU8sS0FBSztBQUNWLFlBQU0sWUFBYSxLQUFLLE9BQU8sSUFBSSxLQUFNLENBQUM7QUFBQSxJQUM1QztBQUNBLFdBQU87QUFBQSxFQUNUOzs7QUNOQSxNQUFNLGFBQWEsT0FBTyxTQUFTLFNBQVM7QUFHckMsTUFBTSxjQUFjO0FBQUEsSUFDdkIsTUFBTTtBQUFBLElBQ04sV0FBVztBQUFBLElBQ1gsYUFBYTtBQUFBLElBQ2IsUUFBUTtBQUFBLElBQ1IsYUFBYTtBQUFBLElBQ2IsUUFBUTtBQUFBLElBQ1IsUUFBUTtBQUFBLElBQ1IsU0FBUztBQUFBLElBQ1QsUUFBUTtBQUFBLElBQ1Is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TUFDaEMscUJBQXFCO0FBQUEsTUFDckIsNkJBQTZCO0FBQUEsTUFDN0IsMEJBQTBCO0FBQUEsTUFDMUIsdUJBQXVCO0FBQUEsTUFDdkIsdUJBQXVCO0FBQUEsTUFDdkIsMkJBQTJCO0FBQUEsTUFDM0IsK0JBQStCO0FBQUEsTUFDL0Isb0JBQW9CO0FBQUEsTUFDcEIscUJBQXFCO0FBQUEsTUFDckIscUJBQXFCO0FBQUEsTUFDckIsc0JBQXNCO0FBQUEsTUFDdEIsZ0NBQWdDO0FBQUEsTUFDaEMsa0NBQWtDO0FBQUEsTUFDbEMsbUNBQW1DO0FBQUEsTUFDbkMsb0NBQW9DO0FBQUEsTUFDcEMsK0JBQStCO0FBQUEsTUFDL0IsNkJBQTZCO0FBQUEsTUFDN0IsdUJBQXVCO0FBQUEsTUFDdkIsaUNBQWlDO0FBQUEsTUFDakMsOEJBQThCO0FBQUEsTUFDOUIsNEJBQTRCO0FBQUEsTUFDNUIsc0NBQXNDO0FBQUEsTUFDdEMsNEJBQTRCO0FBQUEsTUFDNUIsc0JBQXNCO0FBQUEsTUFDdEIsa0NBQWtDO0FBQUEsTUFDbEMsc0JBQXNCO0FBQUEsTUFDdEIsd0JBQXdCO0FBQUEsTUFDeEIsMkJBQTJCO0FBQUEsTUFDM0Isd0JBQXdCO0FBQUEsTUFDeEIsbUJBQW1CO0FBQUEsTUFDbkIsMEJBQTBCO0FBQUEsTUFDMUIsOEJBQThCO0FBQUEsTUFDOUIseUJBQXlCO0FBQUEsTUFDekIsNkJBQTZCO0FBQUEsTUFDN0IsaUJBQWlCO0FBQUEsTUFDakIsZ0JBQWdCO0FBQUEsTUFDaEIsc0JBQXNCO0FBQUEsTUFDdEIsZUFBZTtBQUFBLE1BQ2YseUJBQXlCO0FBQUEsTUFDekIsd0JBQXdCO0FBQUEsTUFDeEIsb0JBQW9CO0FBQUEsTUFDcEIscUJBQXFCO0FBQUEsTUFDckIsaUJBQWlCO0FBQUEsTUFDakIsaUJBQWlCO0FBQUEsTUFDakIsc0JBQXNCO0FBQUEsTUFDdEIsbUNBQW1DO0FBQUEsTUFDbkMscUNBQXFDO0FBQUEsTUFDckMsdUJBQXVCO0FBQUEsTUFDdkIsc0JBQXNCO0FBQUEsTUFDdEIsd0JBQXdCO0FBQUEsTUFDeEIsMkJBQTJCO0FBQUEsTUFDM0IsbUJBQW1CO0FBQUEsTUFDbkIscUJBQXFCO0FBQUEsTUFDckIsc0JBQXNCO0FBQUEsTUFDdEIsc0JBQXNCO0FBQUEsTUFDdEIsOEJBQThCO0FBQUEsTUFDOUIsaUJBQWlCO0FBQUEsTUFDakIseUJBQXlCO0FBQUEsTUFDekIsMkJBQTJCO0FBQUEsTUFDM0IsK0JBQStCO0FBQUEsTUFDL0IsMEJBQTBCO0FBQUEsTUFDMUIsOEJBQThCO0FBQUEsTUFDOUIsaUJBQWlCO0FBQUEsTUFDakIsdUJBQXVCO0FBQUEsTUFDdkIsZ0JBQWdCO0FBQUEsTUFDaEIsMEJBQTBCO0FBQUEsTUFDMUIseUJBQXlCO0FBQUEsTUFDekIsc0JBQXNCO0FBQUEsTUFDdEIsa0JBQWtCO0FBQUEsTUFDbEIsbUJBQW1CO0FBQUEsTUFDbkIsa0JBQWtCO0FBQUEsTUFDbEIsdUJBQXVCO0FBQUEsTUFDdkIsb0NBQW9DO0FBQUEsTUFDcEMsc0NBQXNDO0FBQUEsTUFDdEMsd0JBQXdCO0FBQUEsTUFDeEIsdUJBQXVCO0FBQUEsTUFDdkIseUJBQXlCO0FBQUEsTUFDekIsNEJBQTRCO0FBQUEsTUFDNUIsNEJBQTRCO0FBQUEsTUFDNUIsY0FBYztBQUFBLE1BQ2QsYUFBYTtBQUFBLE1BQ2IsY0FBYztBQUFBLE1BQ2Qsb0JBQW9CO0FBQUEsTUFDcEIsbUJBQW1CO0FBQUEsTUFDbkIsdUJBQXVCO0FBQUEsTUFDdkIsc0JBQXNCO0FBQUEsTUFDdEIscUJBQXFCO0FBQUEsTUFDckIsb0JBQW9CO0FBQUEsTUFDcEIsaUJBQWlCO0FBQUEsTUFDakIsZ0JBQWdCO0FBQUEsTUFDaEIsb0JBQW9CO0FBQUEsTUFDcEIsbUJBQW1CO0FBQUEsTUFDbkIsdUJBQXVCO0FBQUEsTUFDdkIsc0JBQXNCO0FBQUEsTUFDdEIscUJBQXFCO0FBQUEsTUFDckIsb0JBQW9CO0FBQUEsTUFDcEIsZ0JBQWdCO0FBQUEsTUFDaEIsZUFBZTtBQUFBLE1BQ2YsZUFBZTtBQUFBLE1BQ2YsY0FBYztBQUFBLE1BQ2QsMEJBQTBCO0FBQUEsTUFD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TyxZQUFZLGFBQWE7QUFBQSxNQUM1QixhQUFhO0FBQUEsTUFDYixZQUFZO0FBQUEsTUFDWjtBQUFBLE1BQ0E7QUFBQSxJQUNKLENBQUM7QUFBQSxFQUNMOzs7QUNwSkEsU0FBTyxTQUFTLE9BQU8sVUFBVSxDQUFDO0FBOENsQyxTQUFPLE9BQU8sU0FBTztBQUVyQixTQUFPLFFBQVEsT0FBTyxTQUFTLENBQUM7QUFDaEMsU0FBTyxNQUFNLGNBQWM7QUFDM0IsU0FBTyxNQUFNLFVBQVU7QUFDdkIsU0FBTyxNQUFNLE9BQU87QUFDcEIsU0FBTyxNQUFNLFlBQVk7QUFDekIsU0FBTyxNQUFNLFVBQVU7QUFDdkIsU0FBTyxNQUFNLFNBQVM7QUFDdEIsU0FBTyxNQUFNLFFBQVE7QUFDckIsU0FBTyxNQUFNLFVBQVU7QUFDdkIsU0FBTyxNQUFNLFNBQVM7QUFDdEIsU0FBTyxNQUFNLFNBQVM7QUFDdEIsU0FBTyxNQUFNLE1BQU07QUFHbkIsTUFBSSxVQUFVO0FBQ2QsV0FBUyxpQkFBaUIsb0JBQW9CLFdBQVc7QUFDckQsY0FBVTtBQUNWLFdBQU8sT0FBTyxPQUFPLHFCQUFxQjtBQUMxQyxRQUFHLE1BQU87QUFDTixlQUFTLHNCQUFzQjtBQUFBLElBQ25DO0FBQUEsRUFDSixDQUFDO0FBRUQsV0FBUyxVQUFVLElBQUk7QUFDbkIsUUFBSSxXQUFXLFNBQVMsZUFBZSxZQUFZO0FBQy9DLFNBQUc7QUFBQSxJQUNQLE9BQU87QUFDSCxlQUFTLGlCQUFpQixvQkFBb0IsRUFBRTtBQUFBLElBQ3BEO0FBQUEsRUFDSjtBQUVBLFlBQVUsTUFBTTtBQUNaLElBQUksT0FBTztBQUFBLEVBQ2YsQ0FBQzsiLAogICJuYW1lcyI6IFsic2l6ZSIsICJjYWxsIiwgImNhbGwiLCAiY2FsbCIsICJjYWxsIiwgIkhpZGUiLCAiU2hvdyIsICJjYWxsIiwgIndpZHRoIiwgImhlaWdodCIsICJIaWRlIiwgIlNob3ciLCAiY2FsbCIsICJldmVudE5hbWUiLCAiRXJyb3IiLCAiY2FsbCIsICJFcnJvciIsICJjYWxsIiwgImdlbmVyYXRlSUQiXQp9Cg== diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index a42a7997d70..fca71dcf8f8 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -4,11 +4,11 @@ package application import ( "fmt" + "github.com/wailsapp/wails/v3/internal/assetserver/webview" "regexp" "strings" "unsafe" - "github.com/wailsapp/wails/v3/internal/assetserver/webview" "github.com/wailsapp/wails/v3/pkg/events" ) @@ -72,7 +72,7 @@ extern void onDragNDrop( guint time, gpointer data); extern gboolean onKeyPressEvent (GtkWidget *widget, GdkEventKey *event, uintptr_t user_data); -extern void onProcessRequest(void *request, gpointer user_data); +extern void onProcessRequest(WebKitURISchemeRequest *request, uintptr_t user_data); extern void sendMessageToBackend(WebKitUserContentManager *contentManager, WebKitJavascriptResult *result, void *data); // exported below (end) @@ -81,6 +81,10 @@ static void signal_connect(void *widget, char *event, void *cb, void* data) { g_signal_connect(widget, event, cb, data); } +static WebKitWebView* webkit_web_view(GtkWidget *webview) { + return WEBKIT_WEB_VIEW(webview); +} + static void* new_message_dialog(GtkWindow *parent, const gchar *msg, int dialogType, bool hasButtons) { // gtk_message_dialog_new is variadic! Can't call from cgo directly GtkWidget *dialog; @@ -682,7 +686,7 @@ func (w *linuxWebviewWindow) enableDND() { func (w *linuxWebviewWindow) execJS(js string) { value := C.CString(js) - C.webkit_web_view_evaluate_javascript((*C.WebKitWebView)(w.webview), + C.webkit_web_view_evaluate_javascript(w.webKitWebView(), value, C.long(len(js)), nil, @@ -770,24 +774,24 @@ func (w *linuxWebviewWindow) hide() { } func (w *linuxWebviewWindow) isFullscreen() bool { - gdkWindow := C.gtk_widget_get_window((*C.GtkWidget)(w.window)) + gdkWindow := C.gtk_widget_get_window(w.gtkWidget()) state := C.gdk_window_get_state(gdkWindow) return state&C.GDK_WINDOW_STATE_FULLSCREEN > 0 } func (w *linuxWebviewWindow) isFocused() bool { // returns true if window is focused - return C.gtk_window_has_toplevel_focus((*C.GtkWindow)(w.window)) == 1 + return C.gtk_window_has_toplevel_focus(w.gtkWindow()) == 1 } func (w *linuxWebviewWindow) isMaximised() bool { - gdkwindow := C.gtk_widget_get_window((*C.GtkWidget)(w.window)) + gdkwindow := C.gtk_widget_get_window(w.gtkWidget()) state := C.gdk_window_get_state(gdkwindow) return state&C.GDK_WINDOW_STATE_MAXIMIZED > 0 && state&C.GDK_WINDOW_STATE_FULLSCREEN == 0 } func (w *linuxWebviewWindow) isMinimised() bool { - gdkwindow := C.gtk_widget_get_window((*C.GtkWidget)(w.window)) + gdkwindow := C.gtk_widget_get_window(w.gtkWidget()) state := C.gdk_window_get_state(gdkwindow) return state&C.GDK_WINDOW_STATE_ICONIFIED > 0 } @@ -800,11 +804,11 @@ func (w *linuxWebviewWindow) isVisible() bool { } func (w *linuxWebviewWindow) maximise() { - C.gtk_window_maximize((*C.GtkWindow)(w.window)) + C.gtk_window_maximize(w.gtkWindow()) } func (w *linuxWebviewWindow) minimise() { - C.gtk_window_iconify((*C.GtkWindow)(w.window)) + C.gtk_window_iconify(w.gtkWindow()) } func windowNew(application pointer, menu pointer, windowId uint, gpuPolicy WebviewGpuPolicy) (window, webview, vbox pointer) { @@ -830,16 +834,15 @@ func windowNewWebview(parentId uint, gpuPolicy WebviewGpuPolicy) pointer { manager := C.webkit_user_content_manager_new() C.webkit_user_content_manager_register_script_message_handler(manager, c.String("external")) webView := C.webkit_web_view_new_with_user_content_manager(manager) - id := C.uint(parentId) - if !registered { - C.webkit_web_context_register_uri_scheme( - C.webkit_web_context_get_default(), - c.String("wails"), - C.WebKitURISchemeRequestCallback(C.onProcessRequest), - C.gpointer(&id), - nil) - registered = true - } + winID := unsafe.Pointer(uintptr(C.uint(parentId))) + C.g_object_set_data((*C.GObject)(unsafe.Pointer(webView)), c.String("windowid"), C.gpointer(winID)) + context := C.webkit_web_view_get_context(C.webkit_web_view(webView)) + C.webkit_web_context_register_uri_scheme( + context, + c.String("wails"), + C.WebKitURISchemeRequestCallback(C.onProcessRequest), + nil, + nil) settings := C.webkit_web_view_get_settings((*C.WebKitWebView)(unsafe.Pointer(webView))) C.webkit_settings_set_user_agent_with_application_details(settings, c.String("wails.io"), c.String("")) @@ -860,8 +863,8 @@ func windowNewWebview(parentId uint, gpuPolicy WebviewGpuPolicy) pointer { } func (w *linuxWebviewWindow) present() { - C.gtk_window_present((*C.GtkWindow)(w.window)) - // gtk_window_unminimize ((*C.GtkWindow)(w.window)) /// gtk4 + C.gtk_window_present(w.gtkWindow()) + // gtk_window_unminimize (w.gtkWindow()) /// gtk4 } func (w *linuxWebviewWindow) setSize(width, height int) { @@ -949,7 +952,7 @@ func (w *linuxWebviewWindow) setHTML(html string) { } func (w *linuxWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) { - C.gtk_window_set_keep_above((*C.GtkWindow)(w.window), gtkBool(alwaysOnTop)) + C.gtk_window_set_keep_above(w.gtkWindow(), gtkBool(alwaysOnTop)) } func (w *linuxWebviewWindow) setTitle(title string) { @@ -976,7 +979,7 @@ func (w *linuxWebviewWindow) setTransparent() { func (w *linuxWebviewWindow) setURL(uri string) { target := C.CString(uri) - C.webkit_web_view_load_uri((*C.WebKitWebView)(w.webview), target) + C.webkit_web_view_load_uri(w.webKitWebView(), target) C.free(unsafe.Pointer(target)) } @@ -1108,7 +1111,7 @@ func (w *linuxWebviewWindow) zoomReset() { func (w *linuxWebviewWindow) reload() { uri := C.CString("wails://") - C.webkit_web_view_load_uri((*C.WebKitWebView)(w.webview), uri) + C.webkit_web_view_load_uri(w.webKitWebView(), uri) C.free(unsafe.Pointer(uri)) } @@ -1238,10 +1241,11 @@ func getKeyboardState(event *C.GdkEventKey) (string, bool) { } //export onProcessRequest -func onProcessRequest(request unsafe.Pointer, data unsafe.Pointer) { - windowId := uint(*((*C.uint)(data))) +func onProcessRequest(request *C.WebKitURISchemeRequest, data C.uintptr_t) { + webView := C.webkit_uri_scheme_request_get_web_view(request) + windowId := uint(uintptr(C.g_object_get_data((*C.GObject)(unsafe.Pointer(webView)), C.CString("windowid")))) webviewRequests <- &webViewAssetRequest{ - Request: webview.NewRequest(request), + Request: webview.NewRequest(unsafe.Pointer(request)), windowId: windowId, windowName: globalApplication.getWindowForID(windowId).Name(), } From e06df85f026feb64c48dea63b5c39e06b7a98d2a Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 11 Feb 2024 08:34:56 +1100 Subject: [PATCH 067/369] WindowID now correctly processed by postMessage calls. --- v3/pkg/application/linux_cgo.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index fca71dcf8f8..af58cd4f7c2 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -835,7 +835,11 @@ func windowNewWebview(parentId uint, gpuPolicy WebviewGpuPolicy) pointer { C.webkit_user_content_manager_register_script_message_handler(manager, c.String("external")) webView := C.webkit_web_view_new_with_user_content_manager(manager) winID := unsafe.Pointer(uintptr(C.uint(parentId))) + + // attach window id to both the webview and contentmanager C.g_object_set_data((*C.GObject)(unsafe.Pointer(webView)), c.String("windowid"), C.gpointer(winID)) + C.g_object_set_data((*C.GObject)(unsafe.Pointer(manager)), c.String("windowid"), C.gpointer(winID)) + context := C.webkit_web_view_get_context(C.webkit_web_view(webView)) C.webkit_web_context_register_uri_scheme( context, @@ -1255,13 +1259,16 @@ func onProcessRequest(request *C.WebKitURISchemeRequest, data C.uintptr_t) { func sendMessageToBackend(contentManager *C.WebKitUserContentManager, result *C.WebKitJavascriptResult, data unsafe.Pointer) { + // Get the windowID from the contentManager + windowID := uint(uintptr(C.g_object_get_data((*C.GObject)(unsafe.Pointer(contentManager)), C.CString("windowid")))) + var msg string value := C.webkit_javascript_result_get_js_value(result) message := C.jsc_value_to_string(value) msg = C.GoString(message) defer C.g_free(C.gpointer(message)) windowMessageBuffer <- &windowMessage{ - windowId: uint(windowID), + windowId: windowID, message: msg, } } From a60b198b0385ce58f2c4801ba0bbf913a2452602 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 11 Feb 2024 08:58:00 +1100 Subject: [PATCH 068/369] Fix window close issues --- v3/pkg/application/linux_cgo.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index af58cd4f7c2..7bf4362dfe7 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -667,7 +667,7 @@ func widgetSetVisible(widget pointer, hidden bool) { } func (w *linuxWebviewWindow) close() { - C.gtk_window_close((*C.GtkWindow)(w.window)) + C.gtk_widget_destroy(w.gtkWidget()) getNativeApplication().unregisterWindow(windowPointer(w.window)) } @@ -1001,7 +1001,7 @@ func emit(we *C.WindowEvent) { //export handleDeleteEvent func handleDeleteEvent(widget *C.GtkWidget, event *C.GdkEvent, data C.uintptr_t) C.gboolean { processWindowEvent(C.uint(data), C.uint(events.Linux.WindowDeleteEvent)) - return C.gboolean(0) + return C.gboolean(1) } //export handleLoadChanged From be7c723c470260ff1091040e979a264a88abfab7 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 11 Feb 2024 09:07:46 +1100 Subject: [PATCH 069/369] Fix window close issues Update docs Make uri scheme registration thread safe --- mkdocs-website/docs/en/roadmap.md | 10 ++++++ mkdocs-website/shared/alpha1.csv | 32 +++++++++---------- .../shared/alpha3-bindings-callbyname.csv | 6 +--- mkdocs-website/shared/alpha5.csv | 16 ++++++++++ v3/pkg/application/linux_cgo.go | 19 +++++++---- 5 files changed, 55 insertions(+), 28 deletions(-) create mode 100644 mkdocs-website/shared/alpha5.csv diff --git a/mkdocs-website/docs/en/roadmap.md b/mkdocs-website/docs/en/roadmap.md index 875f468101e..559d755089e 100644 --- a/mkdocs-website/docs/en/roadmap.md +++ b/mkdocs-website/docs/en/roadmap.md @@ -23,6 +23,16 @@ Report any issues you find using [this guide](./getting-started/feedback.md). - Test all the things on Linux! +#### Status + +Linux examples: + +- :material-check-bold: - Working +- :material-minus: - Partially working +- :material-close: - Not working + +{{ read_csv("alpha5.csv") }} + ## Upcoming milestones ## Alpha 6 diff --git a/mkdocs-website/shared/alpha1.csv b/mkdocs-website/shared/alpha1.csv index f372dc65f02..1f553d43306 100644 --- a/mkdocs-website/shared/alpha1.csv +++ b/mkdocs-website/shared/alpha1.csv @@ -1,16 +1,16 @@ -" ",Mac,Windows,Linux -binding,:material-check-bold:,:material-check-bold:,:material-check-bold: -build,:material-check-bold:,:material-check-bold:,:material-check-bold: -clipboard,:material-check-bold:,:material-check-bold:,:material-check-bold: -context menus,:material-check-bold:,:material-check-bold:,:material-check-bold: -dialogs,:material-check-bold:,:material-check-bold:,:material-check-bold: -drag-n-drop,:material-check-bold:,:material-check-bold:,:material-check-bold: -events,:material-check-bold:,:material-check-bold:,:material-minus: -frameless,:material-check-bold:,:material-check-bold:,:material-check-bold: -keybindings,:material-check-bold:,:material-check-bold:,:material-minus: -plain,:material-check-bold:,:material-check-bold:,:material-check-bold: -screen,:material-check-bold:,:material-check-bold:,:material-check-bold: -systray,:material-check-bold:,:material-check-bold:,:material-check-bold: -video,:material-check-bold:,:material-check-bold:,:material-check-bold: -window,:material-check-bold:,:material-check-bold:,:material-minus: -wml,:material-check-bold:,:material-check-bold:,:material-check-bold: \ No newline at end of file +" ",Linux,Notes +binding," "," " +build," "," " +clipboard," "," " +context menus," "," " +dialogs," "," " +drag-n-drop," "," " +events,:material-check-bold:," " +frameless," "," " +keybindings," "," " +plain," "," " +screen," "," " +systray," "," " +video," "," " +window," "," " +wml," "," " \ No newline at end of file diff --git a/mkdocs-website/shared/alpha3-bindings-callbyname.csv b/mkdocs-website/shared/alpha3-bindings-callbyname.csv index dbbc00e5c2b..faa8b62d9ba 100644 --- a/mkdocs-website/shared/alpha3-bindings-callbyname.csv +++ b/mkdocs-website/shared/alpha3-bindings-callbyname.csv @@ -1,9 +1,5 @@ Scenario,Windows,Mac,Linux -Same package,: clipboardLock.RLock() - defer clipboardLock.RUnlock() - clipboardText := C.getClipboardText() - result := C.GoString(clipboardText) - return result, true:,:material-check-bold:,:material-check-bold: +Same package,:material-check-bold,:material-check-bold:,:material-check-bold: Different package,:material-check-bold:,:material-check-bold:,:material-check-bold: Different package with same name,"on hold","on hold","on hold" Containing another struct from same package,:material-check-bold:,:material-check-bold:,:material-check-bold: diff --git a/mkdocs-website/shared/alpha5.csv b/mkdocs-website/shared/alpha5.csv new file mode 100644 index 00000000000..f372dc65f02 --- /dev/null +++ b/mkdocs-website/shared/alpha5.csv @@ -0,0 +1,16 @@ +" ",Mac,Windows,Linux +binding,:material-check-bold:,:material-check-bold:,:material-check-bold: +build,:material-check-bold:,:material-check-bold:,:material-check-bold: +clipboard,:material-check-bold:,:material-check-bold:,:material-check-bold: +context menus,:material-check-bold:,:material-check-bold:,:material-check-bold: +dialogs,:material-check-bold:,:material-check-bold:,:material-check-bold: +drag-n-drop,:material-check-bold:,:material-check-bold:,:material-check-bold: +events,:material-check-bold:,:material-check-bold:,:material-minus: +frameless,:material-check-bold:,:material-check-bold:,:material-check-bold: +keybindings,:material-check-bold:,:material-check-bold:,:material-minus: +plain,:material-check-bold:,:material-check-bold:,:material-check-bold: +screen,:material-check-bold:,:material-check-bold:,:material-check-bold: +systray,:material-check-bold:,:material-check-bold:,:material-check-bold: +video,:material-check-bold:,:material-check-bold:,:material-check-bold: +window,:material-check-bold:,:material-check-bold:,:material-minus: +wml,:material-check-bold:,:material-check-bold:,:material-check-bold: \ No newline at end of file diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 7bf4362dfe7..5d0c73fca4b 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -7,6 +7,7 @@ import ( "github.com/wailsapp/wails/v3/internal/assetserver/webview" "regexp" "strings" + "sync" "unsafe" "github.com/wailsapp/wails/v3/pkg/events" @@ -192,6 +193,8 @@ var ( mainThreadId *C.GThread ) +var registerURIScheme sync.Once + func init() { gtkSignalToMenuItem = map[uint]*MenuItem{} @@ -840,13 +843,15 @@ func windowNewWebview(parentId uint, gpuPolicy WebviewGpuPolicy) pointer { C.g_object_set_data((*C.GObject)(unsafe.Pointer(webView)), c.String("windowid"), C.gpointer(winID)) C.g_object_set_data((*C.GObject)(unsafe.Pointer(manager)), c.String("windowid"), C.gpointer(winID)) - context := C.webkit_web_view_get_context(C.webkit_web_view(webView)) - C.webkit_web_context_register_uri_scheme( - context, - c.String("wails"), - C.WebKitURISchemeRequestCallback(C.onProcessRequest), - nil, - nil) + registerURIScheme.Do(func() { + context := C.webkit_web_view_get_context(C.webkit_web_view(webView)) + C.webkit_web_context_register_uri_scheme( + context, + c.String("wails"), + C.WebKitURISchemeRequestCallback(C.onProcessRequest), + nil, + nil) + }) settings := C.webkit_web_view_get_settings((*C.WebKitWebView)(unsafe.Pointer(webView))) C.webkit_settings_set_user_agent_with_application_details(settings, c.String("wails.io"), c.String("")) From e39097a17ed2f21e62fec7014b6b9e8a328689df Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 12 Feb 2024 06:07:39 +1100 Subject: [PATCH 070/369] fix min/max --- v3/examples/dev/go.mod | 28 ++++++++++---------- v3/examples/dev/go.sum | 20 +++++++++++++++ v3/examples/plugins/go.mod | 30 +++++++++++----------- v3/examples/plugins/go.sum | 21 +++++++++++++++ v3/examples/server/go.mod | 28 ++++++++++---------- v3/examples/server/go.sum | 20 +++++++++++++++ v3/examples/video/go.mod | 26 +++++++++---------- v3/examples/video/go.sum | 19 ++++++++++++++ v3/pkg/application/webview_window_linux.go | 15 ++++------- 9 files changed, 142 insertions(+), 65 deletions(-) diff --git a/v3/examples/dev/go.mod b/v3/examples/dev/go.mod index cebd31d2402..22f823993c4 100644 --- a/v3/examples/dev/go.mod +++ b/v3/examples/dev/go.mod @@ -1,17 +1,19 @@ module changeme -go 1.21 +go 1.21.1 + +toolchain go1.22.0 require github.com/wailsapp/wails/v3 v3.0.0-alpha.0 require ( - github.com/Microsoft/go-winio v0.4.16 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/bep/debounce v1.2.1 // indirect github.com/ebitengine/purego v0.4.0-alpha.4 // indirect - github.com/emirpasic/gods v1.12.0 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.2.0 // indirect - github.com/go-git/go-git/v5 v5.3.0 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/go-git/go-git/v5 v5.11.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/google/uuid v1.3.0 // indirect @@ -19,11 +21,11 @@ require ( github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/leaanthony/go-ansi-parser v1.6.1 // indirect github.com/leaanthony/u v1.1.0 // indirect - github.com/lmittmann/tint v1.0.0 // indirect + github.com/lmittmann/tint v1.0.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -31,17 +33,17 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/samber/lo v1.38.1 // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/stretchr/testify v1.8.4 // indirect github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect - github.com/xanzy/ssh-agent v0.3.0 // indirect - golang.org/x/crypto v0.9.0 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/dev/go.sum b/v3/examples/dev/go.sum index acb39d10195..cc2d9be43f6 100644 --- a/v3/examples/dev/go.sum +++ b/v3/examples/dev/go.sum @@ -1,6 +1,8 @@ github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= @@ -17,19 +19,23 @@ github.com/ebitengine/purego v0.4.0-alpha.4 h1:Y7yIV06Yo5M2BAdD7EVPhfp6LZ0tEcQo5 github.com/ebitengine/purego v0.4.0-alpha.4/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-git/go-billy/v5 v5.2.0 h1:GcoouCP9J+5slw2uXAocL70z8ml4A8B/H8nEPt6CLPk= github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc= github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw= +github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= @@ -51,6 +57,7 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -66,6 +73,7 @@ github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI= github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= github.com/lmittmann/tint v1.0.0 h1:fzEj70K1L58uyoePQxKe+ezDZJ5pybiWGdA0JeFvvyw= github.com/lmittmann/tint v1.0.0/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lmittmann/tint v1.0.3/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -94,12 +102,14 @@ github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 h1:3RPlVWzZ/PDqmVuf/FKHARG5EMid/tl7cv54Sw/QRVY= github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -113,31 +123,41 @@ github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhw github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= diff --git a/v3/examples/plugins/go.mod b/v3/examples/plugins/go.mod index e84c04d5326..97d857d2b6d 100644 --- a/v3/examples/plugins/go.mod +++ b/v3/examples/plugins/go.mod @@ -1,20 +1,20 @@ module plugin_demo -go 1.21 +go 1.21.1 -toolchain go1.21.0 +toolchain go1.22.0 require github.com/wailsapp/wails/v3 v3.0.0-alpha.0 require ( - github.com/Microsoft/go-winio v0.4.16 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/bep/debounce v1.2.1 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/ebitengine/purego v0.4.0-alpha.4 // indirect - github.com/emirpasic/gods v1.12.0 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.2.0 // indirect - github.com/go-git/go-git/v5 v5.3.0 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/go-git/go-git/v5 v5.11.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/google/uuid v1.3.0 // indirect @@ -23,11 +23,11 @@ require ( github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/leaanthony/go-ansi-parser v1.6.1 // indirect github.com/leaanthony/u v1.1.0 // indirect - github.com/lmittmann/tint v1.0.0 // indirect + github.com/lmittmann/tint v1.0.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -37,19 +37,19 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/samber/lo v1.38.1 // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/stretchr/testify v1.8.4 // indirect github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect - github.com/xanzy/ssh-agent v0.3.0 // indirect - golang.org/x/crypto v0.9.0 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/tools v0.6.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect lukechampine.com/uint128 v1.2.0 // indirect modernc.org/cc/v3 v3.40.0 // indirect diff --git a/v3/examples/plugins/go.sum b/v3/examples/plugins/go.sum index 499a8e0ad92..4ca499dc0ed 100644 --- a/v3/examples/plugins/go.sum +++ b/v3/examples/plugins/go.sum @@ -1,6 +1,8 @@ github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= @@ -19,19 +21,23 @@ github.com/ebitengine/purego v0.4.0-alpha.4 h1:Y7yIV06Yo5M2BAdD7EVPhfp6LZ0tEcQo5 github.com/ebitengine/purego v0.4.0-alpha.4/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-git/go-billy/v5 v5.2.0 h1:GcoouCP9J+5slw2uXAocL70z8ml4A8B/H8nEPt6CLPk= github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc= github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw= +github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= @@ -57,6 +63,7 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -72,6 +79,7 @@ github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI= github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= github.com/lmittmann/tint v1.0.0 h1:fzEj70K1L58uyoePQxKe+ezDZJ5pybiWGdA0JeFvvyw= github.com/lmittmann/tint v1.0.0/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lmittmann/tint v1.0.3/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -105,12 +113,14 @@ github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 h1:3RPlVWzZ/PDqmVuf/FKHARG5EMid/tl7cv54Sw/QRVY= github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -124,10 +134,13 @@ github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhw github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= @@ -135,24 +148,31 @@ golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= @@ -163,6 +183,7 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/v3/examples/server/go.mod b/v3/examples/server/go.mod index bf3a7c2037f..8b3eeb2505d 100644 --- a/v3/examples/server/go.mod +++ b/v3/examples/server/go.mod @@ -1,19 +1,19 @@ module server_demo -go 1.21 +go 1.21.1 -toolchain go1.21.0 +toolchain go1.22.0 require github.com/wailsapp/wails/v3 v3.0.0-alpha.0 require ( - github.com/Microsoft/go-winio v0.4.16 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/bep/debounce v1.2.1 // indirect github.com/ebitengine/purego v0.4.0-alpha.4 // indirect - github.com/emirpasic/gods v1.12.0 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.2.0 // indirect - github.com/go-git/go-git/v5 v5.3.0 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/go-git/go-git/v5 v5.11.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/google/uuid v1.3.0 // indirect @@ -21,11 +21,11 @@ require ( github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/leaanthony/go-ansi-parser v1.6.1 // indirect github.com/leaanthony/u v1.1.0 // indirect - github.com/lmittmann/tint v1.0.0 // indirect + github.com/lmittmann/tint v1.0.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -33,17 +33,17 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/samber/lo v1.38.1 // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/stretchr/testify v1.8.4 // indirect github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect - github.com/xanzy/ssh-agent v0.3.0 // indirect - golang.org/x/crypto v0.9.0 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/server/go.sum b/v3/examples/server/go.sum index acb39d10195..cc2d9be43f6 100644 --- a/v3/examples/server/go.sum +++ b/v3/examples/server/go.sum @@ -1,6 +1,8 @@ github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= @@ -17,19 +19,23 @@ github.com/ebitengine/purego v0.4.0-alpha.4 h1:Y7yIV06Yo5M2BAdD7EVPhfp6LZ0tEcQo5 github.com/ebitengine/purego v0.4.0-alpha.4/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-git/go-billy/v5 v5.2.0 h1:GcoouCP9J+5slw2uXAocL70z8ml4A8B/H8nEPt6CLPk= github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc= github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw= +github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= @@ -51,6 +57,7 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -66,6 +73,7 @@ github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI= github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= github.com/lmittmann/tint v1.0.0 h1:fzEj70K1L58uyoePQxKe+ezDZJ5pybiWGdA0JeFvvyw= github.com/lmittmann/tint v1.0.0/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lmittmann/tint v1.0.3/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -94,12 +102,14 @@ github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 h1:3RPlVWzZ/PDqmVuf/FKHARG5EMid/tl7cv54Sw/QRVY= github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -113,31 +123,41 @@ github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhw github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= diff --git a/v3/examples/video/go.mod b/v3/examples/video/go.mod index edfa98f91a3..6c4d665c4d9 100644 --- a/v3/examples/video/go.mod +++ b/v3/examples/video/go.mod @@ -1,19 +1,19 @@ module frameless -go 1.21 +go 1.21.1 -toolchain go1.21.0 +toolchain go1.22.0 require github.com/wailsapp/wails/v3 v3.0.0-alpha.0 require ( - github.com/Microsoft/go-winio v0.4.16 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/bep/debounce v1.2.1 // indirect github.com/ebitengine/purego v0.4.0-alpha.4 // indirect - github.com/emirpasic/gods v1.12.0 // indirect - github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.2.0 // indirect - github.com/go-git/go-git/v5 v5.3.0 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/go-git/go-git/v5 v5.11.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/google/uuid v1.3.0 // indirect @@ -21,10 +21,10 @@ require ( github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/leaanthony/go-ansi-parser v1.6.1 // indirect github.com/leaanthony/u v1.1.0 // indirect - github.com/lmittmann/tint v1.0.0 // indirect + github.com/lmittmann/tint v1.0.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -36,11 +36,11 @@ require ( github.com/sergi/go-diff v1.2.0 // indirect github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect - github.com/xanzy/ssh-agent v0.3.0 // indirect - golang.org/x/crypto v0.9.0 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/video/go.sum b/v3/examples/video/go.sum index 169c421b948..64dddcbbf0e 100644 --- a/v3/examples/video/go.sum +++ b/v3/examples/video/go.sum @@ -1,6 +1,8 @@ github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= @@ -17,19 +19,23 @@ github.com/ebitengine/purego v0.4.0-alpha.4 h1:Y7yIV06Yo5M2BAdD7EVPhfp6LZ0tEcQo5 github.com/ebitengine/purego v0.4.0-alpha.4/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-git/go-billy/v5 v5.2.0 h1:GcoouCP9J+5slw2uXAocL70z8ml4A8B/H8nEPt6CLPk= github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc= github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw= +github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= @@ -51,6 +57,7 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= @@ -65,6 +72,7 @@ github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI= github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= github.com/lmittmann/tint v1.0.0 h1:fzEj70K1L58uyoePQxKe+ezDZJ5pybiWGdA0JeFvvyw= github.com/lmittmann/tint v1.0.0/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lmittmann/tint v1.0.3/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -95,6 +103,7 @@ github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -107,31 +116,41 @@ github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhw github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 8a4a4d09a17..38b6f71fdbe 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -95,8 +95,7 @@ func (w *linuxWebviewWindow) isNormal() bool { } func (w *linuxWebviewWindow) setFullscreenButtonEnabled(enabled bool) { - // C.setFullscreenButtonEnabled(w.nsWindow, C.bool(enabled)) - fmt.Println("setFullscreenButtonEnabled - not implemented") + // Not implemented } func (w *linuxWebviewWindow) disableSizeConstraints() { @@ -156,17 +155,13 @@ func newWindowImpl(parent *WebviewWindow) *linuxWebviewWindow { } func (w *linuxWebviewWindow) setMinMaxSize(minWidth, minHeight, maxWidth, maxHeight int) { - if minWidth == 0 { - minWidth = -1 - } - if minHeight == 0 { - minHeight = -1 - } + // Get current screen for window + _, _, monitorwidth, monitorheight, _ := w.getCurrentMonitorGeometry() if maxWidth == 0 { - maxWidth = math.MaxInt + maxWidth = monitorwidth } if maxHeight == 0 { - maxHeight = math.MaxInt + maxHeight = monitorheight } windowSetGeometryHints(w.window, minWidth, minHeight, maxWidth, maxHeight) } From 12e2e2101ac4642c8ae5cd6e78649a6061de18a6 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 12 Feb 2024 06:27:04 +1100 Subject: [PATCH 071/369] fix screens --- v3/pkg/application/linux_cgo.go | 50 +++++++++++++++++++++- v3/pkg/application/screen_linux.go | 12 +++++- v3/pkg/application/webview_window_linux.go | 16 ------- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 5d0c73fca4b..8f2606dbc86 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -618,9 +618,10 @@ func getScreenByIndex(display *C.struct__GdkDisplay, index int) *Screen { if C.gdk_monitor_is_primary(monitor) == 1 { primary = true } + name := C.gdk_monitor_get_model(monitor) return &Screen{ ID: fmt.Sprintf("%d", index), - Name: fmt.Sprintf("Screen %d", index), + Name: C.GoString(name), IsPrimary: primary, Scale: float32(C.gdk_monitor_get_scale_factor(monitor)), X: int(geometry.x), @@ -733,6 +734,25 @@ func (w *linuxWebviewWindow) getCurrentMonitor() *C.GdkMonitor { return C.gdk_display_get_monitor_at_window(display, gdkWindow) } +func (w *linuxWebviewWindow) getScreen() (*Screen, error) { + // Get the current screen for the window + monitor := w.getCurrentMonitor() + name := C.gdk_monitor_get_model(monitor) + mx, my, width, height, scale := w.getCurrentMonitorGeometry() + return &Screen{ + ID: fmt.Sprintf("%d", w.id), // A unique identifier for the display + Name: C.GoString(name), // The name of the display + Scale: float32(scale), // The scale factor of the display + X: mx, // The x-coordinate of the top-left corner of the rectangle + Y: my, // The y-coordinate of the top-left corner of the rectangle + Size: Size{Width: width, Height: height}, // The size of the display + Bounds: Rect{}, // The bounds of the display + WorkArea: Rect{}, // The work area of the display + IsPrimary: false, // Whether this is the primary display + Rotation: 0.0, // The rotation of the display + }, nil +} + func (w *linuxWebviewWindow) getCurrentMonitorGeometry() (x int, y int, width int, height int, scale int) { monitor := w.getCurrentMonitor() if monitor == nil { @@ -929,6 +949,34 @@ func (w *linuxWebviewWindow) setBackgroundColour(colour RGBA) { C.free(unsafe.Pointer(cssStr)) } +func getPrimaryScreen() (*Screen, error) { + display := C.gdk_display_get_default() + monitor := C.gdk_display_get_primary_monitor(display) + geometry := C.GdkRectangle{} + C.gdk_monitor_get_geometry(monitor, &geometry) + scale := int(C.gdk_monitor_get_scale_factor(monitor)) + // get the name for the screen + name := C.gdk_monitor_get_model(monitor) + return &Screen{ + ID: "0", + Name: C.GoString(name), + IsPrimary: true, + X: int(geometry.x), + Y: int(geometry.y), + Size: Size{ + Height: int(geometry.height), + Width: int(geometry.width), + }, + Bounds: Rect{ + X: int(geometry.x), + Y: int(geometry.y), + Height: int(geometry.height), + Width: int(geometry.width), + }, + Scale: float32(scale), + }, nil +} + func windowSetGeometryHints(window pointer, minWidth, minHeight, maxWidth, maxHeight int) { size := C.GdkGeometry{ min_width: C.int(minWidth), diff --git a/v3/pkg/application/screen_linux.go b/v3/pkg/application/screen_linux.go index d93cfbd927e..f6dfdf59d36 100644 --- a/v3/pkg/application/screen_linux.go +++ b/v3/pkg/application/screen_linux.go @@ -3,12 +3,20 @@ package application import ( - "fmt" "sync" ) func (a *linuxApp) getPrimaryScreen() (*Screen, error) { - return nil, fmt.Errorf("not implemented") + var wg sync.WaitGroup + var screen *Screen + var err error + wg.Add(1) + InvokeSync(func() { + screen, err = getPrimaryScreen() + wg.Done() + }) + wg.Wait() + return screen, err } func (a *linuxApp) getScreens() ([]*Screen, error) { diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 38b6f71fdbe..448d383fb2f 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -70,22 +70,6 @@ func (w *linuxWebviewWindow) openContextMenu(menu *Menu, data *ContextMenuData) w.contextMenuShow(native, data) } -func (w *linuxWebviewWindow) getScreen() (*Screen, error) { - mx, my, width, height, scale := w.getCurrentMonitorGeometry() - return &Screen{ - ID: fmt.Sprintf("%d", w.id), // A unique identifier for the display - Name: w.parent.Name(), // The name of the display - Scale: float32(scale), // The scale factor of the display - X: mx, // The x-coordinate of the top-left corner of the rectangle - Y: my, // The y-coordinate of the top-left corner of the rectangle - Size: Size{Width: width, Height: height}, // The size of the display - Bounds: Rect{}, // The bounds of the display - WorkArea: Rect{}, // The work area of the display - IsPrimary: false, // Whether this is the primary display - Rotation: 0.0, // The rotation of the display - }, nil -} - func (w *linuxWebviewWindow) focus() { w.present() } From 161444107a93e6af384392fbdb78b3ee7448704e Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 12 Feb 2024 22:01:52 +1100 Subject: [PATCH 072/369] Support linux systrays, of sorts... --- v2/go.mod | 4 +- v3/examples/binding/go.mod | 4 +- v3/examples/binding/go.sum | 12 +- v3/examples/dev/go.mod | 4 +- v3/examples/dev/go.sum | 2 + v3/examples/frameless/go.mod | 4 +- v3/examples/frameless/go.sum | 2 + v3/examples/plugins/go.mod | 4 +- v3/examples/plugins/go.sum | 2 + v3/examples/server/go.mod | 4 +- v3/examples/server/go.sum | 2 + v3/examples/systray/main.go | 3 +- v3/examples/video/go.mod | 4 +- v3/examples/video/go.sum | 2 + v3/go.mod | 8 +- v3/go.sum | 8 + .../@wailsio/runtime/src/event_types.js | 2 + .../@wailsio/runtime/types/event_types.d.ts | 2 + v3/pkg/application/linux_cgo.go | 58 +- v3/pkg/application/menu.go | 4 + v3/pkg/application/systemtray_linux.go | 76 +- v3/pkg/application/webview_window_linux.go | 6 + v3/pkg/events/events.go | 690 +++++++++--------- v3/pkg/events/events.txt | 2 + v3/pkg/events/events_darwin.h | 250 +++---- v3/pkg/events/events_linux.h | 6 +- 26 files changed, 662 insertions(+), 503 deletions(-) diff --git a/v2/go.mod b/v2/go.mod index a2d0ab416b8..aef70015a27 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -1,6 +1,8 @@ module github.com/wailsapp/wails/v2 -go 1.20 +go 1.21 + +toolchain go1.22.0 require ( github.com/Masterminds/semver v1.5.0 diff --git a/v3/examples/binding/go.mod b/v3/examples/binding/go.mod index d53e53e657d..963d59f479a 100644 --- a/v3/examples/binding/go.mod +++ b/v3/examples/binding/go.mod @@ -39,11 +39,11 @@ require ( github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/binding/go.sum b/v3/examples/binding/go.sum index b451aafd047..53111bf10b4 100644 --- a/v3/examples/binding/go.sum +++ b/v3/examples/binding/go.sum @@ -110,8 +110,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -150,15 +150,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/v3/examples/dev/go.mod b/v3/examples/dev/go.mod index 22f823993c4..33fde4e41f8 100644 --- a/v3/examples/dev/go.mod +++ b/v3/examples/dev/go.mod @@ -40,10 +40,10 @@ require ( github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.17.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/dev/go.sum b/v3/examples/dev/go.sum index cc2d9be43f6..817d628318a 100644 --- a/v3/examples/dev/go.sum +++ b/v3/examples/dev/go.sum @@ -130,6 +130,7 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -158,6 +159,7 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= diff --git a/v3/examples/frameless/go.mod b/v3/examples/frameless/go.mod index ab2668fb5a8..358eb760227 100644 --- a/v3/examples/frameless/go.mod +++ b/v3/examples/frameless/go.mod @@ -39,11 +39,11 @@ require ( github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/frameless/go.sum b/v3/examples/frameless/go.sum index 858cff35cf4..1b0b965ca4f 100644 --- a/v3/examples/frameless/go.sum +++ b/v3/examples/frameless/go.sum @@ -112,6 +112,7 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -152,6 +153,7 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= diff --git a/v3/examples/plugins/go.mod b/v3/examples/plugins/go.mod index 97d857d2b6d..a31d9eb8a9a 100644 --- a/v3/examples/plugins/go.mod +++ b/v3/examples/plugins/go.mod @@ -44,11 +44,11 @@ require ( github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect lukechampine.com/uint128 v1.2.0 // indirect diff --git a/v3/examples/plugins/go.sum b/v3/examples/plugins/go.sum index 4ca499dc0ed..cbc968c45ea 100644 --- a/v3/examples/plugins/go.sum +++ b/v3/examples/plugins/go.sum @@ -141,6 +141,7 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= @@ -173,6 +174,7 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= diff --git a/v3/examples/server/go.mod b/v3/examples/server/go.mod index 8b3eeb2505d..4ebf1edafab 100644 --- a/v3/examples/server/go.mod +++ b/v3/examples/server/go.mod @@ -40,10 +40,10 @@ require ( github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.17.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/server/go.sum b/v3/examples/server/go.sum index cc2d9be43f6..817d628318a 100644 --- a/v3/examples/server/go.sum +++ b/v3/examples/server/go.sum @@ -130,6 +130,7 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -158,6 +159,7 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= diff --git a/v3/examples/systray/main.go b/v3/examples/systray/main.go index 592ce58c109..c2853152051 100644 --- a/v3/examples/systray/main.go +++ b/v3/examples/systray/main.go @@ -2,7 +2,6 @@ package main import ( _ "embed" - "fmt" "log" "runtime" @@ -25,6 +24,7 @@ func main() { window := app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ Width: 500, Height: 800, + Name: "Systray Demo Window", Frameless: true, AlwaysOnTop: true, Hidden: true, @@ -79,7 +79,6 @@ func main() { radioCallback := func(ctx *application.Context) { menuItem := ctx.ClickedMenuItem() menuItem.SetLabel(menuItem.Label() + "!") - fmt.Println("radioCallback: ") } // Radio groups are created implicitly by placing radio items next to each other in a menu diff --git a/v3/examples/video/go.mod b/v3/examples/video/go.mod index 6c4d665c4d9..525e941b491 100644 --- a/v3/examples/video/go.mod +++ b/v3/examples/video/go.mod @@ -37,10 +37,10 @@ require ( github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.17.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/video/go.sum b/v3/examples/video/go.sum index 64dddcbbf0e..f59a0e5caef 100644 --- a/v3/examples/video/go.sum +++ b/v3/examples/video/go.sum @@ -123,6 +123,7 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -151,6 +152,7 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= diff --git a/v3/go.mod b/v3/go.mod index 51f502bea2f..0eade4d33a4 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -36,7 +36,7 @@ require ( github.com/tc-hib/winres v0.1.6 github.com/wailsapp/go-webview2 v1.0.9 github.com/wailsapp/mimetype v1.4.1 - golang.org/x/sys v0.15.0 + golang.org/x/sys v0.17.0 modernc.org/sqlite v1.21.0 ) @@ -90,14 +90,14 @@ require ( github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect - golang.org/x/image v0.5.0 // indirect + golang.org/x/image v0.15.0 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.19.0 // indirect golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect golang.org/x/sync v0.4.0 // indirect - golang.org/x/term v0.15.0 // indirect + golang.org/x/term v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.13.0 // indirect google.golang.org/appengine v1.6.6 // indirect diff --git a/v3/go.sum b/v3/go.sum index ecdad413e66..527c3bb67dc 100644 --- a/v3/go.sum +++ b/v3/go.sum @@ -390,6 +390,8 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -408,6 +410,8 @@ golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= +golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= +golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -534,6 +538,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -543,6 +549,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.js b/v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.js index b5d0015ef73..f39ec6a908d 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.js +++ b/v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.js @@ -157,6 +157,8 @@ export const EventTypes = { SystemThemeChanged: "linux:SystemThemeChanged", WindowLoadChanged: "linux:WindowLoadChanged", WindowDeleteEvent: "linux:WindowDeleteEvent", + WindowFocusIn: "linux:WindowFocusIn", + WindowFocusOut: "linux:WindowFocusOut", ApplicationStartup: "linux:ApplicationStartup", }, Common: { diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/types/event_types.d.ts b/v3/internal/runtime/desktop/@wailsio/runtime/types/event_types.d.ts index dad1f2f7a37..744bb437b91 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/types/event_types.d.ts +++ b/v3/internal/runtime/desktop/@wailsio/runtime/types/event_types.d.ts @@ -157,6 +157,8 @@ export declare const EventTypes: { SystemThemeChanged: string, WindowLoadChanged: string, WindowDeleteEvent: string, + WindowFocusIn: string, + WindowFocusOut: string, ApplicationStartup: string, }, Common: { diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 8f2606dbc86..df8eff50e72 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -60,6 +60,7 @@ typedef struct WindowEvent { void activateLinux(gpointer data); extern void emit(WindowEvent* data); extern gboolean handleDeleteEvent(GtkWidget*, GdkEvent*, uintptr_t); +extern gboolean handleFocusEvent(GtkWidget*, GdkEvent*, uintptr_t); extern void handleLoadChanged(WebKitWebView*, WebKitLoadEvent, uintptr_t); void handleClick(void*); extern gboolean onButtonEvent(GtkWidget *widget, GdkEventButton *event, uintptr_t user_data); @@ -701,6 +702,31 @@ func (w *linuxWebviewWindow) execJS(js string) { C.free(unsafe.Pointer(value)) } +func getMousePosition() (int, int, *Screen) { + var x, y C.gint + var screen *C.GdkScreen + defaultDisplay := C.gdk_display_get_default() + device := C.gdk_seat_get_pointer(C.gdk_display_get_default_seat(defaultDisplay)) + C.gdk_device_get_position(device, &screen, &x, &y) + // Get Monitor for screen + monitor := C.gdk_display_get_monitor_at_point(defaultDisplay, x, y) + geometry := C.GdkRectangle{} + C.gdk_monitor_get_geometry(monitor, &geometry) + scale := int(C.gdk_monitor_get_scale_factor(monitor)) + return int(x), int(y), &Screen{ + ID: fmt.Sprintf("%d", 0), // A unique identifier for the display + Name: C.GoString(C.gdk_monitor_get_model(monitor)), // The name of the display + Scale: float32(scale), // The scale factor of the display + X: int(geometry.x), // The x-coordinate of the top-left corner of the rectangle + Y: int(geometry.y), // The y-coordinate of the top-left corner of the rectangle + Size: Size{Width: int(geometry.width), Height: int(geometry.height)}, // The size of the display + Bounds: Rect{}, // The bounds of the display + WorkArea: Rect{}, // The work area of the display + IsPrimary: false, // Whether this is the primary display + Rotation: 0.0, // The rotation of the display + } +} + func (w *linuxWebviewWindow) destroy() { w.parent.markAsDestroyed() // Free menu @@ -708,7 +734,8 @@ func (w *linuxWebviewWindow) destroy() { C.gtk_widget_destroy((*C.GtkWidget)(w.gtkmenu)) w.gtkmenu = nil } - w.destroy() + // Free window + C.gtk_widget_destroy(w.gtkWidget()) } func (w *linuxWebviewWindow) fullscreen() { @@ -908,7 +935,7 @@ func (w *linuxWebviewWindow) show() { return } C.gtk_widget_show_all(w.gtkWidget()) - w.setAbsolutePosition(w.lastX, w.lastY) + //w.setAbsolutePosition(w.lastX, w.lastY) } func windowIgnoreMouseEvents(window pointer, webview pointer, ignore bool) { @@ -1057,6 +1084,19 @@ func handleDeleteEvent(widget *C.GtkWidget, event *C.GdkEvent, data C.uintptr_t) return C.gboolean(1) } +//export handleFocusEvent +func handleFocusEvent(widget *C.GtkWidget, event *C.GdkEvent, data C.uintptr_t) C.gboolean { + focusEvent := (*C.GdkEventFocus)(unsafe.Pointer(event)) + if focusEvent._type == C.GDK_FOCUS_CHANGE { + if focusEvent.in == C.TRUE { + processWindowEvent(C.uint(data), C.uint(events.Linux.WindowFocusIn)) + } else { + processWindowEvent(C.uint(data), C.uint(events.Linux.WindowFocusOut)) + } + } + return C.gboolean(0) +} + //export handleLoadChanged func handleLoadChanged(webview *C.WebKitWebView, event C.WebKitLoadEvent, data C.uintptr_t) { switch event { @@ -1075,6 +1115,7 @@ func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventT // Set up the window close event wv := unsafe.Pointer(w.webview) C.signal_connect(unsafe.Pointer(w.window), c.String("delete-event"), C.handleDeleteEvent, winID) + C.signal_connect(unsafe.Pointer(w.window), c.String("focus-out-event"), C.handleFocusEvent, winID) C.signal_connect(wv, c.String("load-changed"), C.handleLoadChanged, winID) contentManager := C.webkit_web_view_get_user_content_manager(w.webKitWebView()) @@ -1111,6 +1152,14 @@ func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventT C.signal_connect(wv, c.String("key-press-event"), C.onKeyPressEvent, winID) } +func getMouseButtons() (bool, bool, bool) { + var pointer *C.GdkDevice + var state C.GdkModifierType + pointer = C.gdk_seat_get_pointer(C.gdk_display_get_default_seat(C.gdk_display_get_default())) + C.gdk_device_get_state(pointer, nil, nil, &state) + return state&C.GDK_BUTTON1_MASK > 0, state&C.GDK_BUTTON2_MASK > 0, state&C.GDK_BUTTON3_MASK > 0 +} + func openDevTools(webview pointer) { inspector := C.webkit_web_view_get_inspector((*C.WebKitWebView)(webview)) C.webkit_web_inspector_show(inspector) @@ -1180,7 +1229,8 @@ func (w *linuxWebviewWindow) setZoom(zoom float64) { } func (w *linuxWebviewWindow) move(x, y int) { - C.gtk_window_move((*C.GtkWindow)(w.window), C.int(x), C.int(y)) + // Move the window to these coordinates + C.gtk_window_move(w.gtkWindow(), C.int(x), C.int(y)) } func (w *linuxWebviewWindow) absolutePosition() (int, int) { @@ -1380,7 +1430,7 @@ func runChooserDialog(window pointer, allowMultiple, createFolders, showHidden b gtkFilters := []*C.GtkFileFilter{} for _, filter := range filters { - f := (C.gtk_file_filter_new()) + f := C.gtk_file_filter_new() displayStr := C.CString(filter.DisplayName) C.gtk_file_filter_set_name(f, displayStr) C.free(unsafe.Pointer(displayStr)) diff --git a/v3/pkg/application/menu.go b/v3/pkg/application/menu.go index 25a844a4509..ae75c00ad9f 100644 --- a/v3/pkg/application/menu.go +++ b/v3/pkg/application/menu.go @@ -106,6 +106,10 @@ func (m *Menu) clone() *Menu { return result } +func (m *Menu) Append(in *Menu) { + m.items = append(m.items, in.items...) +} + func (a *App) NewMenu() *Menu { return &Menu{} } diff --git a/v3/pkg/application/systemtray_linux.go b/v3/pkg/application/systemtray_linux.go index 43501c95290..2468e7ff18a 100644 --- a/v3/pkg/application/systemtray_linux.go +++ b/v3/pkg/application/systemtray_linux.go @@ -24,6 +24,8 @@ const ( ) type linuxSystemTray struct { + parent *SystemTray + id uint label string icon []byte @@ -41,6 +43,11 @@ type linuxSystemTray struct { itemMap map[int32]*systrayMenuItem } +func (s *linuxSystemTray) getScreen() (*Screen, error) { + _, _, result := getMousePosition() + return result, nil +} + // dbusMenu is a named struct to map into generated bindings. // It represents the layout of a menu item type dbusMenu = struct { @@ -182,6 +189,22 @@ func (s *linuxSystemTray) refresh() { } func (s *linuxSystemTray) setMenu(menu *Menu) { + if s.parent.attachedWindow.Window != nil { + temp := menu + menu = NewMenu() + title := "Open" + if s.parent.attachedWindow.Window.Name() != "" { + title += " " + s.parent.attachedWindow.Window.Name() + } else { + title += " window" + } + openMenuItem := menu.Add(title) + openMenuItem.OnClick(func(*Context) { + s.parent.clickHandler() + }) + menu.AddSeparator() + menu.Append(temp) + } s.itemMap = map[int32]*systrayMenuItem{} // our root menu element s.itemMap[0] = &systrayMenuItem{ @@ -198,16 +221,47 @@ func (s *linuxSystemTray) setMenu(menu *Menu) { } func (s *linuxSystemTray) positionWindow(window *WebviewWindow, offset int) error { - return nil -} + // Get the mouse location on the screen + mouseX, mouseY, currentScreen := getMousePosition() + screenBounds := currentScreen.Size -func (s *linuxSystemTray) getScreen() (*Screen, error) { - // FIXME: How do we get the screen we are on? - return &Screen{}, nil + // Calculate new X position + newX := mouseX - (window.Width() / 2) + + // Check if the window goes out of the screen bounds on the left side + if newX < 0 { + newX = 0 + } + + // Check if the window goes out of the screen bounds on the right side + if newX+window.Width() > screenBounds.Width { + newX = screenBounds.Width - window.Width() + } + + // Calculate new Y position + newY := mouseY - (window.Height() / 2) + + // Check if the window goes out of the screen bounds on the top + if newY < 0 { + newY = 0 + } + + // Check if the window goes out of the screen bounds on the bottom + if newY+window.Height() > screenBounds.Height { + newY = screenBounds.Height - window.Height() - offset + } + + // Set the new position of the window + window.SetAbsolutePosition(newX, newY) + return nil } func (s *linuxSystemTray) bounds() (*Rect, error) { + + // Best effort guess at the screen bounds + return &Rect{}, nil + } func (s *linuxSystemTray) run() { @@ -354,6 +408,7 @@ func newSystemTrayImpl(s *SystemTray) systemTrayImpl { } return &linuxSystemTray{ + parent: s, id: s.id, label: label, icon: s.icon, @@ -572,6 +627,16 @@ func (s *linuxSystemTray) Event(id int32, eventID string, data dbus.Variant, tim InvokeAsync(item.menuItem.handleClick) } } + if eventID == "opened" { + if s.parent.onMenuOpen != nil { + s.parent.onMenuOpen() + } + } + if eventID == "closed" { + if s.parent.onMenuClose != nil { + s.parent.onMenuClose() + } + } return } @@ -583,6 +648,7 @@ func (s *linuxSystemTray) EventGroup(events []struct { V3 uint32 }) (idErrors []int32, err *dbus.Error) { for _, event := range events { + fmt.Printf("EventGroup: %v, %v, %v, %v\n", event.V0, event.V1, event.V2, event.V3) if event.V1 == "clicked" { item, ok := s.itemMap[event.V0] if ok { diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 448d383fb2f..5dd82f79132 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -264,6 +264,12 @@ func (w *linuxWebviewWindow) run() { w.execJS(js) } }) + w.parent.On(events.Linux.WindowFocusIn, func(e *WindowEvent) { + w.parent.emit(events.Common.WindowFocus) + }) + w.parent.On(events.Linux.WindowFocusOut, func(e *WindowEvent) { + w.parent.emit(events.Common.WindowLostFocus) + }) w.parent.On(events.Linux.WindowDeleteEvent, func(e *WindowEvent) { w.parent.emit(events.Common.WindowClosing) }) diff --git a/v3/pkg/events/events.go b/v3/pkg/events/events.go index 1923c87e7ce..d3ce4f50cb7 100644 --- a/v3/pkg/events/events.go +++ b/v3/pkg/events/events.go @@ -31,27 +31,27 @@ type commonEvents struct { func newCommonEvents() commonEvents { return commonEvents{ - ApplicationStarted: 1177, - WindowMaximise: 1178, - WindowUnMaximise: 1179, - WindowFullscreen: 1180, - WindowUnFullscreen: 1181, - WindowRestore: 1182, - WindowMinimise: 1183, - WindowUnMinimise: 1184, - WindowClosing: 1185, - WindowZoom: 1186, - WindowZoomIn: 1187, - WindowZoomOut: 1188, - WindowZoomReset: 1189, - WindowFocus: 1190, - WindowLostFocus: 1191, - WindowShow: 1192, - WindowHide: 1193, - WindowDPIChanged: 1194, - WindowFilesDropped: 1195, - WindowRuntimeReady: 1196, - ThemeChanged: 1197, + ApplicationStarted: 1179, + WindowMaximise: 1180, + WindowUnMaximise: 1181, + WindowFullscreen: 1182, + WindowUnFullscreen: 1183, + WindowRestore: 1184, + WindowMinimise: 1185, + WindowUnMinimise: 1186, + WindowClosing: 1187, + WindowZoom: 1188, + WindowZoomIn: 1189, + WindowZoomOut: 1190, + WindowZoomReset: 1191, + WindowFocus: 1192, + WindowLostFocus: 1193, + WindowShow: 1194, + WindowHide: 1195, + WindowDPIChanged: 1196, + WindowFilesDropped: 1197, + WindowRuntimeReady: 1198, + ThemeChanged: 1199, } } @@ -61,6 +61,8 @@ type linuxEvents struct { SystemThemeChanged ApplicationEventType WindowLoadChanged WindowEventType WindowDeleteEvent WindowEventType + WindowFocusIn WindowEventType + WindowFocusOut WindowEventType ApplicationStartup ApplicationEventType } @@ -69,7 +71,9 @@ func newLinuxEvents() linuxEvents { SystemThemeChanged: 1024, WindowLoadChanged: 1025, WindowDeleteEvent: 1026, - ApplicationStartup: 1027, + WindowFocusIn: 1027, + WindowFocusOut: 1028, + ApplicationStartup: 1029, } } @@ -204,130 +208,130 @@ type macEvents struct { func newMacEvents() macEvents { return macEvents{ - ApplicationDidBecomeActive: 1028, - ApplicationDidChangeBackingProperties: 1029, - ApplicationDidChangeEffectiveAppearance: 1030, - ApplicationDidChangeIcon: 1031, - ApplicationDidChangeOcclusionState: 1032, - ApplicationDidChangeScreenParameters: 1033, - ApplicationDidChangeStatusBarFrame: 1034, - ApplicationDidChangeStatusBarOrientation: 1035, - ApplicationDidFinishLaunching: 1036, - ApplicationDidHide: 1037, - ApplicationDidResignActiveNotification: 1038, - ApplicationDidUnhide: 1039, - ApplicationDidUpdate: 1040, - ApplicationWillBecomeActive: 1041, - ApplicationWillFinishLaunching: 1042, - ApplicationWillHide: 1043, - ApplicationWillResignActive: 1044, - ApplicationWillTerminate: 1045, - ApplicationWillUnhide: 1046, - ApplicationWillUpdate: 1047, - ApplicationDidChangeTheme: 1048, - ApplicationShouldHandleReopen: 1049, - WindowDidBecomeKey: 1050, - WindowDidBecomeMain: 1051, - WindowDidBeginSheet: 1052, - WindowDidChangeAlpha: 1053, - WindowDidChangeBackingLocation: 1054, - WindowDidChangeBackingProperties: 1055, - WindowDidChangeCollectionBehavior: 1056, - WindowDidChangeEffectiveAppearance: 1057, - WindowDidChangeOcclusionState: 1058, - WindowDidChangeOrderingMode: 1059, - WindowDidChangeScreen: 1060, - WindowDidChangeScreenParameters: 1061, - WindowDidChangeScreenProfile: 1062, - WindowDidChangeScreenSpace: 1063, - WindowDidChangeScreenSpaceProperties: 1064, - WindowDidChangeSharingType: 1065, - WindowDidChangeSpace: 1066, - WindowDidChangeSpaceOrderingMode: 1067, - WindowDidChangeTitle: 1068, - WindowDidChangeToolbar: 1069, - WindowDidChangeVisibility: 1070, - WindowDidDeminiaturize: 1071, - WindowDidEndSheet: 1072, - WindowDidEnterFullScreen: 1073, - WindowDidEnterVersionBrowser: 1074, - WindowDidExitFullScreen: 1075, - WindowDidExitVersionBrowser: 1076, - WindowDidExpose: 1077, - WindowDidFocus: 1078, - WindowDidMiniaturize: 1079, - WindowDidMove: 1080, - WindowDidOrderOffScreen: 1081, - WindowDidOrderOnScreen: 1082, - WindowDidResignKey: 1083, - WindowDidResignMain: 1084, - WindowDidResize: 1085, - WindowDidUpdate: 1086, - WindowDidUpdateAlpha: 1087, - WindowDidUpdateCollectionBehavior: 1088, - WindowDidUpdateCollectionProperties: 1089, - WindowDidUpdateShadow: 1090, - WindowDidUpdateTitle: 1091, - WindowDidUpdateToolbar: 1092, - WindowDidUpdateVisibility: 1093, - WindowShouldClose: 1094, - WindowWillBecomeKey: 1095, - WindowWillBecomeMain: 1096, - WindowWillBeginSheet: 1097, - WindowWillChangeOrderingMode: 1098, - WindowWillClose: 1099, - WindowWillDeminiaturize: 1100, - WindowWillEnterFullScreen: 1101, - WindowWillEnterVersionBrowser: 1102, - WindowWillExitFullScreen: 1103, - WindowWillExitVersionBrowser: 1104, - WindowWillFocus: 1105, - WindowWillMiniaturize: 1106, - WindowWillMove: 1107, - WindowWillOrderOffScreen: 1108, - WindowWillOrderOnScreen: 1109, - WindowWillResignMain: 1110, - WindowWillResize: 1111, - WindowWillUnfocus: 1112, - WindowWillUpdate: 1113, - WindowWillUpdateAlpha: 1114, - WindowWillUpdateCollectionBehavior: 1115, - WindowWillUpdateCollectionProperties: 1116, - WindowWillUpdateShadow: 1117, - WindowWillUpdateTitle: 1118, - WindowWillUpdateToolbar: 1119, - WindowWillUpdateVisibility: 1120, - WindowWillUseStandardFrame: 1121, - MenuWillOpen: 1122, - MenuDidOpen: 1123, - MenuDidClose: 1124, - MenuWillSendAction: 1125, - MenuDidSendAction: 1126, - MenuWillHighlightItem: 1127, - MenuDidHighlightItem: 1128, - MenuWillDisplayItem: 1129, - MenuDidDisplayItem: 1130, - MenuWillAddItem: 1131, - MenuDidAddItem: 1132, - MenuWillRemoveItem: 1133, - MenuDidRemoveItem: 1134, - MenuWillBeginTracking: 1135, - MenuDidBeginTracking: 1136, - MenuWillEndTracking: 1137, - MenuDidEndTracking: 1138, - MenuWillUpdate: 1139, - MenuDidUpdate: 1140, - MenuWillPopUp: 1141, - MenuDidPopUp: 1142, - MenuWillSendActionToItem: 1143, - MenuDidSendActionToItem: 1144, - WebViewDidStartProvisionalNavigation: 1145, - WebViewDidReceiveServerRedirectForProvisionalNavigation: 1146, - WebViewDidFinishNavigation: 1147, - WebViewDidCommitNavigation: 1148, - WindowFileDraggingEntered: 1149, - WindowFileDraggingPerformed: 1150, - WindowFileDraggingExited: 1151, + ApplicationDidBecomeActive: 1030, + ApplicationDidChangeBackingProperties: 1031, + ApplicationDidChangeEffectiveAppearance: 1032, + ApplicationDidChangeIcon: 1033, + ApplicationDidChangeOcclusionState: 1034, + ApplicationDidChangeScreenParameters: 1035, + ApplicationDidChangeStatusBarFrame: 1036, + ApplicationDidChangeStatusBarOrientation: 1037, + ApplicationDidFinishLaunching: 1038, + ApplicationDidHide: 1039, + ApplicationDidResignActiveNotification: 1040, + ApplicationDidUnhide: 1041, + ApplicationDidUpdate: 1042, + ApplicationWillBecomeActive: 1043, + ApplicationWillFinishLaunching: 1044, + ApplicationWillHide: 1045, + ApplicationWillResignActive: 1046, + ApplicationWillTerminate: 1047, + ApplicationWillUnhide: 1048, + ApplicationWillUpdate: 1049, + ApplicationDidChangeTheme: 1050, + ApplicationShouldHandleReopen: 1051, + WindowDidBecomeKey: 1052, + WindowDidBecomeMain: 1053, + WindowDidBeginSheet: 1054, + WindowDidChangeAlpha: 1055, + WindowDidChangeBackingLocation: 1056, + WindowDidChangeBackingProperties: 1057, + WindowDidChangeCollectionBehavior: 1058, + WindowDidChangeEffectiveAppearance: 1059, + WindowDidChangeOcclusionState: 1060, + WindowDidChangeOrderingMode: 1061, + WindowDidChangeScreen: 1062, + WindowDidChangeScreenParameters: 1063, + WindowDidChangeScreenProfile: 1064, + WindowDidChangeScreenSpace: 1065, + WindowDidChangeScreenSpaceProperties: 1066, + WindowDidChangeSharingType: 1067, + WindowDidChangeSpace: 1068, + WindowDidChangeSpaceOrderingMode: 1069, + WindowDidChangeTitle: 1070, + WindowDidChangeToolbar: 1071, + WindowDidChangeVisibility: 1072, + WindowDidDeminiaturize: 1073, + WindowDidEndSheet: 1074, + WindowDidEnterFullScreen: 1075, + WindowDidEnterVersionBrowser: 1076, + WindowDidExitFullScreen: 1077, + WindowDidExitVersionBrowser: 1078, + WindowDidExpose: 1079, + WindowDidFocus: 1080, + WindowDidMiniaturize: 1081, + WindowDidMove: 1082, + WindowDidOrderOffScreen: 1083, + WindowDidOrderOnScreen: 1084, + WindowDidResignKey: 1085, + WindowDidResignMain: 1086, + WindowDidResize: 1087, + WindowDidUpdate: 1088, + WindowDidUpdateAlpha: 1089, + WindowDidUpdateCollectionBehavior: 1090, + WindowDidUpdateCollectionProperties: 1091, + WindowDidUpdateShadow: 1092, + WindowDidUpdateTitle: 1093, + WindowDidUpdateToolbar: 1094, + WindowDidUpdateVisibility: 1095, + WindowShouldClose: 1096, + WindowWillBecomeKey: 1097, + WindowWillBecomeMain: 1098, + WindowWillBeginSheet: 1099, + WindowWillChangeOrderingMode: 1100, + WindowWillClose: 1101, + WindowWillDeminiaturize: 1102, + WindowWillEnterFullScreen: 1103, + WindowWillEnterVersionBrowser: 1104, + WindowWillExitFullScreen: 1105, + WindowWillExitVersionBrowser: 1106, + WindowWillFocus: 1107, + WindowWillMiniaturize: 1108, + WindowWillMove: 1109, + WindowWillOrderOffScreen: 1110, + WindowWillOrderOnScreen: 1111, + WindowWillResignMain: 1112, + WindowWillResize: 1113, + WindowWillUnfocus: 1114, + WindowWillUpdate: 1115, + WindowWillUpdateAlpha: 1116, + WindowWillUpdateCollectionBehavior: 1117, + WindowWillUpdateCollectionProperties: 1118, + WindowWillUpdateShadow: 1119, + WindowWillUpdateTitle: 1120, + WindowWillUpdateToolbar: 1121, + WindowWillUpdateVisibility: 1122, + WindowWillUseStandardFrame: 1123, + MenuWillOpen: 1124, + MenuDidOpen: 1125, + MenuDidClose: 1126, + MenuWillSendAction: 1127, + MenuDidSendAction: 1128, + MenuWillHighlightItem: 1129, + MenuDidHighlightItem: 1130, + MenuWillDisplayItem: 1131, + MenuDidDisplayItem: 1132, + MenuWillAddItem: 1133, + MenuDidAddItem: 1134, + MenuWillRemoveItem: 1135, + MenuDidRemoveItem: 1136, + MenuWillBeginTracking: 1137, + MenuDidBeginTracking: 1138, + MenuWillEndTracking: 1139, + MenuDidEndTracking: 1140, + MenuWillUpdate: 1141, + MenuDidUpdate: 1142, + MenuWillPopUp: 1143, + MenuDidPopUp: 1144, + MenuWillSendActionToItem: 1145, + MenuDidSendActionToItem: 1146, + WebViewDidStartProvisionalNavigation: 1147, + WebViewDidReceiveServerRedirectForProvisionalNavigation: 1148, + WebViewDidFinishNavigation: 1149, + WebViewDidCommitNavigation: 1150, + WindowFileDraggingEntered: 1151, + WindowFileDraggingPerformed: 1152, + WindowFileDraggingExited: 1153, } } @@ -363,31 +367,31 @@ type windowsEvents struct { func newWindowsEvents() windowsEvents { return windowsEvents{ - SystemThemeChanged: 1152, - APMPowerStatusChange: 1153, - APMSuspend: 1154, - APMResumeAutomatic: 1155, - APMResumeSuspend: 1156, - APMPowerSettingChange: 1157, - ApplicationStarted: 1158, - WebViewNavigationCompleted: 1159, - WindowInactive: 1160, - WindowActive: 1161, - WindowClickActive: 1162, - WindowMaximise: 1163, - WindowUnMaximise: 1164, - WindowFullscreen: 1165, - WindowUnFullscreen: 1166, - WindowRestore: 1167, - WindowMinimise: 1168, - WindowUnMinimise: 1169, - WindowClose: 1170, - WindowSetFocus: 1171, - WindowKillFocus: 1172, - WindowDragDrop: 1173, - WindowDragEnter: 1174, - WindowDragLeave: 1175, - WindowDragOver: 1176, + SystemThemeChanged: 1154, + APMPowerStatusChange: 1155, + APMSuspend: 1156, + APMResumeAutomatic: 1157, + APMResumeSuspend: 1158, + APMPowerSettingChange: 1159, + ApplicationStarted: 1160, + WebViewNavigationCompleted: 1161, + WindowInactive: 1162, + WindowActive: 1163, + WindowClickActive: 1164, + WindowMaximise: 1165, + WindowUnMaximise: 1166, + WindowFullscreen: 1167, + WindowUnFullscreen: 1168, + WindowRestore: 1169, + WindowMinimise: 1170, + WindowUnMinimise: 1171, + WindowClose: 1172, + WindowSetFocus: 1173, + WindowKillFocus: 1174, + WindowDragDrop: 1175, + WindowDragEnter: 1176, + WindowDragLeave: 1177, + WindowDragOver: 1178, } } @@ -399,175 +403,177 @@ var eventToJS = map[uint]string{ 1024: "linux:SystemThemeChanged", 1025: "linux:WindowLoadChanged", 1026: "linux:WindowDeleteEvent", - 1027: "linux:ApplicationStartup", - 1028: "mac:ApplicationDidBecomeActive", - 1029: "mac:ApplicationDidChangeBackingProperties", - 1030: "mac:ApplicationDidChangeEffectiveAppearance", - 1031: "mac:ApplicationDidChangeIcon", - 1032: "mac:ApplicationDidChangeOcclusionState", - 1033: "mac:ApplicationDidChangeScreenParameters", - 1034: "mac:ApplicationDidChangeStatusBarFrame", - 1035: "mac:ApplicationDidChangeStatusBarOrientation", - 1036: "mac:ApplicationDidFinishLaunching", - 1037: "mac:ApplicationDidHide", - 1038: "mac:ApplicationDidResignActiveNotification", - 1039: "mac:ApplicationDidUnhide", - 1040: "mac:ApplicationDidUpdate", - 1041: "mac:ApplicationWillBecomeActive", - 1042: "mac:ApplicationWillFinishLaunching", - 1043: "mac:ApplicationWillHide", - 1044: "mac:ApplicationWillResignActive", - 1045: "mac:ApplicationWillTerminate", - 1046: "mac:ApplicationWillUnhide", - 1047: "mac:ApplicationWillUpdate", - 1048: "mac:ApplicationDidChangeTheme!", - 1049: "mac:ApplicationShouldHandleReopen!", - 1050: "mac:WindowDidBecomeKey", - 1051: "mac:WindowDidBecomeMain", - 1052: "mac:WindowDidBeginSheet", - 1053: "mac:WindowDidChangeAlpha", - 1054: "mac:WindowDidChangeBackingLocation", - 1055: "mac:WindowDidChangeBackingProperties", - 1056: "mac:WindowDidChangeCollectionBehavior", - 1057: "mac:WindowDidChangeEffectiveAppearance", - 1058: "mac:WindowDidChangeOcclusionState", - 1059: "mac:WindowDidChangeOrderingMode", - 1060: "mac:WindowDidChangeScreen", - 1061: "mac:WindowDidChangeScreenParameters", - 1062: "mac:WindowDidChangeScreenProfile", - 1063: "mac:WindowDidChangeScreenSpace", - 1064: "mac:WindowDidChangeScreenSpaceProperties", - 1065: "mac:WindowDidChangeSharingType", - 1066: "mac:WindowDidChangeSpace", - 1067: "mac:WindowDidChangeSpaceOrderingMode", - 1068: "mac:WindowDidChangeTitle", - 1069: "mac:WindowDidChangeToolbar", - 1070: "mac:WindowDidChangeVisibility", - 1071: "mac:WindowDidDeminiaturize", - 1072: "mac:WindowDidEndSheet", - 1073: "mac:WindowDidEnterFullScreen", - 1074: "mac:WindowDidEnterVersionBrowser", - 1075: "mac:WindowDidExitFullScreen", - 1076: "mac:WindowDidExitVersionBrowser", - 1077: "mac:WindowDidExpose", - 1078: "mac:WindowDidFocus", - 1079: "mac:WindowDidMiniaturize", - 1080: "mac:WindowDidMove", - 1081: "mac:WindowDidOrderOffScreen", - 1082: "mac:WindowDidOrderOnScreen", - 1083: "mac:WindowDidResignKey", - 1084: "mac:WindowDidResignMain", - 1085: "mac:WindowDidResize", - 1086: "mac:WindowDidUpdate", - 1087: "mac:WindowDidUpdateAlpha", - 1088: "mac:WindowDidUpdateCollectionBehavior", - 1089: "mac:WindowDidUpdateCollectionProperties", - 1090: "mac:WindowDidUpdateShadow", - 1091: "mac:WindowDidUpdateTitle", - 1092: "mac:WindowDidUpdateToolbar", - 1093: "mac:WindowDidUpdateVisibility", - 1094: "mac:WindowShouldClose!", - 1095: "mac:WindowWillBecomeKey", - 1096: "mac:WindowWillBecomeMain", - 1097: "mac:WindowWillBeginSheet", - 1098: "mac:WindowWillChangeOrderingMode", - 1099: "mac:WindowWillClose", - 1100: "mac:WindowWillDeminiaturize", - 1101: "mac:WindowWillEnterFullScreen", - 1102: "mac:WindowWillEnterVersionBrowser", - 1103: "mac:WindowWillExitFullScreen", - 1104: "mac:WindowWillExitVersionBrowser", - 1105: "mac:WindowWillFocus", - 1106: "mac:WindowWillMiniaturize", - 1107: "mac:WindowWillMove", - 1108: "mac:WindowWillOrderOffScreen", - 1109: "mac:WindowWillOrderOnScreen", - 1110: "mac:WindowWillResignMain", - 1111: "mac:WindowWillResize", - 1112: "mac:WindowWillUnfocus", - 1113: "mac:WindowWillUpdate", - 1114: "mac:WindowWillUpdateAlpha", - 1115: "mac:WindowWillUpdateCollectionBehavior", - 1116: "mac:WindowWillUpdateCollectionProperties", - 1117: "mac:WindowWillUpdateShadow", - 1118: "mac:WindowWillUpdateTitle", - 1119: "mac:WindowWillUpdateToolbar", - 1120: "mac:WindowWillUpdateVisibility", - 1121: "mac:WindowWillUseStandardFrame", - 1122: "mac:MenuWillOpen", - 1123: "mac:MenuDidOpen", - 1124: "mac:MenuDidClose", - 1125: "mac:MenuWillSendAction", - 1126: "mac:MenuDidSendAction", - 1127: "mac:MenuWillHighlightItem", - 1128: "mac:MenuDidHighlightItem", - 1129: "mac:MenuWillDisplayItem", - 1130: "mac:MenuDidDisplayItem", - 1131: "mac:MenuWillAddItem", - 1132: "mac:MenuDidAddItem", - 1133: "mac:MenuWillRemoveItem", - 1134: "mac:MenuDidRemoveItem", - 1135: "mac:MenuWillBeginTracking", - 1136: "mac:MenuDidBeginTracking", - 1137: "mac:MenuWillEndTracking", - 1138: "mac:MenuDidEndTracking", - 1139: "mac:MenuWillUpdate", - 1140: "mac:MenuDidUpdate", - 1141: "mac:MenuWillPopUp", - 1142: "mac:MenuDidPopUp", - 1143: "mac:MenuWillSendActionToItem", - 1144: "mac:MenuDidSendActionToItem", - 1145: "mac:WebViewDidStartProvisionalNavigation", - 1146: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation", - 1147: "mac:WebViewDidFinishNavigation", - 1148: "mac:WebViewDidCommitNavigation", - 1149: "mac:WindowFileDraggingEntered", - 1150: "mac:WindowFileDraggingPerformed", - 1151: "mac:WindowFileDraggingExited", - 1152: "windows:SystemThemeChanged", - 1153: "windows:APMPowerStatusChange", - 1154: "windows:APMSuspend", - 1155: "windows:APMResumeAutomatic", - 1156: "windows:APMResumeSuspend", - 1157: "windows:APMPowerSettingChange", - 1158: "windows:ApplicationStarted", - 1159: "windows:WebViewNavigationCompleted", - 1160: "windows:WindowInactive", - 1161: "windows:WindowActive", - 1162: "windows:WindowClickActive", - 1163: "windows:WindowMaximise", - 1164: "windows:WindowUnMaximise", - 1165: "windows:WindowFullscreen", - 1166: "windows:WindowUnFullscreen", - 1167: "windows:WindowRestore", - 1168: "windows:WindowMinimise", - 1169: "windows:WindowUnMinimise", - 1170: "windows:WindowClose", - 1171: "windows:WindowSetFocus", - 1172: "windows:WindowKillFocus", - 1173: "windows:WindowDragDrop", - 1174: "windows:WindowDragEnter", - 1175: "windows:WindowDragLeave", - 1176: "windows:WindowDragOver", - 1177: "common:ApplicationStarted", - 1178: "common:WindowMaximise", - 1179: "common:WindowUnMaximise", - 1180: "common:WindowFullscreen", - 1181: "common:WindowUnFullscreen", - 1182: "common:WindowRestore", - 1183: "common:WindowMinimise", - 1184: "common:WindowUnMinimise", - 1185: "common:WindowClosing", - 1186: "common:WindowZoom", - 1187: "common:WindowZoomIn", - 1188: "common:WindowZoomOut", - 1189: "common:WindowZoomReset", - 1190: "common:WindowFocus", - 1191: "common:WindowLostFocus", - 1192: "common:WindowShow", - 1193: "common:WindowHide", - 1194: "common:WindowDPIChanged", - 1195: "common:WindowFilesDropped", - 1196: "common:WindowRuntimeReady", - 1197: "common:ThemeChanged", + 1027: "linux:WindowFocusIn", + 1028: "linux:WindowFocusOut", + 1029: "linux:ApplicationStartup", + 1030: "mac:ApplicationDidBecomeActive", + 1031: "mac:ApplicationDidChangeBackingProperties", + 1032: "mac:ApplicationDidChangeEffectiveAppearance", + 1033: "mac:ApplicationDidChangeIcon", + 1034: "mac:ApplicationDidChangeOcclusionState", + 1035: "mac:ApplicationDidChangeScreenParameters", + 1036: "mac:ApplicationDidChangeStatusBarFrame", + 1037: "mac:ApplicationDidChangeStatusBarOrientation", + 1038: "mac:ApplicationDidFinishLaunching", + 1039: "mac:ApplicationDidHide", + 1040: "mac:ApplicationDidResignActiveNotification", + 1041: "mac:ApplicationDidUnhide", + 1042: "mac:ApplicationDidUpdate", + 1043: "mac:ApplicationWillBecomeActive", + 1044: "mac:ApplicationWillFinishLaunching", + 1045: "mac:ApplicationWillHide", + 1046: "mac:ApplicationWillResignActive", + 1047: "mac:ApplicationWillTerminate", + 1048: "mac:ApplicationWillUnhide", + 1049: "mac:ApplicationWillUpdate", + 1050: "mac:ApplicationDidChangeTheme!", + 1051: "mac:ApplicationShouldHandleReopen!", + 1052: "mac:WindowDidBecomeKey", + 1053: "mac:WindowDidBecomeMain", + 1054: "mac:WindowDidBeginSheet", + 1055: "mac:WindowDidChangeAlpha", + 1056: "mac:WindowDidChangeBackingLocation", + 1057: "mac:WindowDidChangeBackingProperties", + 1058: "mac:WindowDidChangeCollectionBehavior", + 1059: "mac:WindowDidChangeEffectiveAppearance", + 1060: "mac:WindowDidChangeOcclusionState", + 1061: "mac:WindowDidChangeOrderingMode", + 1062: "mac:WindowDidChangeScreen", + 1063: "mac:WindowDidChangeScreenParameters", + 1064: "mac:WindowDidChangeScreenProfile", + 1065: "mac:WindowDidChangeScreenSpace", + 1066: "mac:WindowDidChangeScreenSpaceProperties", + 1067: "mac:WindowDidChangeSharingType", + 1068: "mac:WindowDidChangeSpace", + 1069: "mac:WindowDidChangeSpaceOrderingMode", + 1070: "mac:WindowDidChangeTitle", + 1071: "mac:WindowDidChangeToolbar", + 1072: "mac:WindowDidChangeVisibility", + 1073: "mac:WindowDidDeminiaturize", + 1074: "mac:WindowDidEndSheet", + 1075: "mac:WindowDidEnterFullScreen", + 1076: "mac:WindowDidEnterVersionBrowser", + 1077: "mac:WindowDidExitFullScreen", + 1078: "mac:WindowDidExitVersionBrowser", + 1079: "mac:WindowDidExpose", + 1080: "mac:WindowDidFocus", + 1081: "mac:WindowDidMiniaturize", + 1082: "mac:WindowDidMove", + 1083: "mac:WindowDidOrderOffScreen", + 1084: "mac:WindowDidOrderOnScreen", + 1085: "mac:WindowDidResignKey", + 1086: "mac:WindowDidResignMain", + 1087: "mac:WindowDidResize", + 1088: "mac:WindowDidUpdate", + 1089: "mac:WindowDidUpdateAlpha", + 1090: "mac:WindowDidUpdateCollectionBehavior", + 1091: "mac:WindowDidUpdateCollectionProperties", + 1092: "mac:WindowDidUpdateShadow", + 1093: "mac:WindowDidUpdateTitle", + 1094: "mac:WindowDidUpdateToolbar", + 1095: "mac:WindowDidUpdateVisibility", + 1096: "mac:WindowShouldClose!", + 1097: "mac:WindowWillBecomeKey", + 1098: "mac:WindowWillBecomeMain", + 1099: "mac:WindowWillBeginSheet", + 1100: "mac:WindowWillChangeOrderingMode", + 1101: "mac:WindowWillClose", + 1102: "mac:WindowWillDeminiaturize", + 1103: "mac:WindowWillEnterFullScreen", + 1104: "mac:WindowWillEnterVersionBrowser", + 1105: "mac:WindowWillExitFullScreen", + 1106: "mac:WindowWillExitVersionBrowser", + 1107: "mac:WindowWillFocus", + 1108: "mac:WindowWillMiniaturize", + 1109: "mac:WindowWillMove", + 1110: "mac:WindowWillOrderOffScreen", + 1111: "mac:WindowWillOrderOnScreen", + 1112: "mac:WindowWillResignMain", + 1113: "mac:WindowWillResize", + 1114: "mac:WindowWillUnfocus", + 1115: "mac:WindowWillUpdate", + 1116: "mac:WindowWillUpdateAlpha", + 1117: "mac:WindowWillUpdateCollectionBehavior", + 1118: "mac:WindowWillUpdateCollectionProperties", + 1119: "mac:WindowWillUpdateShadow", + 1120: "mac:WindowWillUpdateTitle", + 1121: "mac:WindowWillUpdateToolbar", + 1122: "mac:WindowWillUpdateVisibility", + 1123: "mac:WindowWillUseStandardFrame", + 1124: "mac:MenuWillOpen", + 1125: "mac:MenuDidOpen", + 1126: "mac:MenuDidClose", + 1127: "mac:MenuWillSendAction", + 1128: "mac:MenuDidSendAction", + 1129: "mac:MenuWillHighlightItem", + 1130: "mac:MenuDidHighlightItem", + 1131: "mac:MenuWillDisplayItem", + 1132: "mac:MenuDidDisplayItem", + 1133: "mac:MenuWillAddItem", + 1134: "mac:MenuDidAddItem", + 1135: "mac:MenuWillRemoveItem", + 1136: "mac:MenuDidRemoveItem", + 1137: "mac:MenuWillBeginTracking", + 1138: "mac:MenuDidBeginTracking", + 1139: "mac:MenuWillEndTracking", + 1140: "mac:MenuDidEndTracking", + 1141: "mac:MenuWillUpdate", + 1142: "mac:MenuDidUpdate", + 1143: "mac:MenuWillPopUp", + 1144: "mac:MenuDidPopUp", + 1145: "mac:MenuWillSendActionToItem", + 1146: "mac:MenuDidSendActionToItem", + 1147: "mac:WebViewDidStartProvisionalNavigation", + 1148: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation", + 1149: "mac:WebViewDidFinishNavigation", + 1150: "mac:WebViewDidCommitNavigation", + 1151: "mac:WindowFileDraggingEntered", + 1152: "mac:WindowFileDraggingPerformed", + 1153: "mac:WindowFileDraggingExited", + 1154: "windows:SystemThemeChanged", + 1155: "windows:APMPowerStatusChange", + 1156: "windows:APMSuspend", + 1157: "windows:APMResumeAutomatic", + 1158: "windows:APMResumeSuspend", + 1159: "windows:APMPowerSettingChange", + 1160: "windows:ApplicationStarted", + 1161: "windows:WebViewNavigationCompleted", + 1162: "windows:WindowInactive", + 1163: "windows:WindowActive", + 1164: "windows:WindowClickActive", + 1165: "windows:WindowMaximise", + 1166: "windows:WindowUnMaximise", + 1167: "windows:WindowFullscreen", + 1168: "windows:WindowUnFullscreen", + 1169: "windows:WindowRestore", + 1170: "windows:WindowMinimise", + 1171: "windows:WindowUnMinimise", + 1172: "windows:WindowClose", + 1173: "windows:WindowSetFocus", + 1174: "windows:WindowKillFocus", + 1175: "windows:WindowDragDrop", + 1176: "windows:WindowDragEnter", + 1177: "windows:WindowDragLeave", + 1178: "windows:WindowDragOver", + 1179: "common:ApplicationStarted", + 1180: "common:WindowMaximise", + 1181: "common:WindowUnMaximise", + 1182: "common:WindowFullscreen", + 1183: "common:WindowUnFullscreen", + 1184: "common:WindowRestore", + 1185: "common:WindowMinimise", + 1186: "common:WindowUnMinimise", + 1187: "common:WindowClosing", + 1188: "common:WindowZoom", + 1189: "common:WindowZoomIn", + 1190: "common:WindowZoomOut", + 1191: "common:WindowZoomReset", + 1192: "common:WindowFocus", + 1193: "common:WindowLostFocus", + 1194: "common:WindowShow", + 1195: "common:WindowHide", + 1196: "common:WindowDPIChanged", + 1197: "common:WindowFilesDropped", + 1198: "common:WindowRuntimeReady", + 1199: "common:ThemeChanged", } diff --git a/v3/pkg/events/events.txt b/v3/pkg/events/events.txt index 2703e48afb8..455170c3995 100644 --- a/v3/pkg/events/events.txt +++ b/v3/pkg/events/events.txt @@ -1,6 +1,8 @@ linux:SystemThemeChanged linux:WindowLoadChanged linux:WindowDeleteEvent +linux:WindowFocusIn +linux:WindowFocusOut linux:ApplicationStartup mac:ApplicationDidBecomeActive mac:ApplicationDidChangeBackingProperties diff --git a/v3/pkg/events/events_darwin.h b/v3/pkg/events/events_darwin.h index 7c224e05248..f8ee81be2b1 100644 --- a/v3/pkg/events/events_darwin.h +++ b/v3/pkg/events/events_darwin.h @@ -6,132 +6,132 @@ extern void processApplicationEvent(unsigned int, void* data); extern void processWindowEvent(unsigned int, unsigned int); -#define EventApplicationDidBecomeActive 1028 -#define EventApplicationDidChangeBackingProperties 1029 -#define EventApplicationDidChangeEffectiveAppearance 1030 -#define EventApplicationDidChangeIcon 1031 -#define EventApplicationDidChangeOcclusionState 1032 -#define EventApplicationDidChangeScreenParameters 1033 -#define EventApplicationDidChangeStatusBarFrame 1034 -#define EventApplicationDidChangeStatusBarOrientation 1035 -#define EventApplicationDidFinishLaunching 1036 -#define EventApplicationDidHide 1037 -#define EventApplicationDidResignActiveNotification 1038 -#define EventApplicationDidUnhide 1039 -#define EventApplicationDidUpdate 1040 -#define EventApplicationWillBecomeActive 1041 -#define EventApplicationWillFinishLaunching 1042 -#define EventApplicationWillHide 1043 -#define EventApplicationWillResignActive 1044 -#define EventApplicationWillTerminate 1045 -#define EventApplicationWillUnhide 1046 -#define EventApplicationWillUpdate 1047 -#define EventApplicationDidChangeTheme 1048 -#define EventApplicationShouldHandleReopen 1049 -#define EventWindowDidBecomeKey 1050 -#define EventWindowDidBecomeMain 1051 -#define EventWindowDidBeginSheet 1052 -#define EventWindowDidChangeAlpha 1053 -#define EventWindowDidChangeBackingLocation 1054 -#define EventWindowDidChangeBackingProperties 1055 -#define EventWindowDidChangeCollectionBehavior 1056 -#define EventWindowDidChangeEffectiveAppearance 1057 -#define EventWindowDidChangeOcclusionState 1058 -#define EventWindowDidChangeOrderingMode 1059 -#define EventWindowDidChangeScreen 1060 -#define EventWindowDidChangeScreenParameters 1061 -#define EventWindowDidChangeScreenProfile 1062 -#define EventWindowDidChangeScreenSpace 1063 -#define EventWindowDidChangeScreenSpaceProperties 1064 -#define EventWindowDidChangeSharingType 1065 -#define EventWindowDidChangeSpace 1066 -#define EventWindowDidChangeSpaceOrderingMode 1067 -#define EventWindowDidChangeTitle 1068 -#define EventWindowDidChangeToolbar 1069 -#define EventWindowDidChangeVisibility 1070 -#define EventWindowDidDeminiaturize 1071 -#define EventWindowDidEndSheet 1072 -#define EventWindowDidEnterFullScreen 1073 -#define EventWindowDidEnterVersionBrowser 1074 -#define EventWindowDidExitFullScreen 1075 -#define EventWindowDidExitVersionBrowser 1076 -#define EventWindowDidExpose 1077 -#define EventWindowDidFocus 1078 -#define EventWindowDidMiniaturize 1079 -#define EventWindowDidMove 1080 -#define EventWindowDidOrderOffScreen 1081 -#define EventWindowDidOrderOnScreen 1082 -#define EventWindowDidResignKey 1083 -#define EventWindowDidResignMain 1084 -#define EventWindowDidResize 1085 -#define EventWindowDidUpdate 1086 -#define EventWindowDidUpdateAlpha 1087 -#define EventWindowDidUpdateCollectionBehavior 1088 -#define EventWindowDidUpdateCollectionProperties 1089 -#define EventWindowDidUpdateShadow 1090 -#define EventWindowDidUpdateTitle 1091 -#define EventWindowDidUpdateToolbar 1092 -#define EventWindowDidUpdateVisibility 1093 -#define EventWindowShouldClose 1094 -#define EventWindowWillBecomeKey 1095 -#define EventWindowWillBecomeMain 1096 -#define EventWindowWillBeginSheet 1097 -#define EventWindowWillChangeOrderingMode 1098 -#define EventWindowWillClose 1099 -#define EventWindowWillDeminiaturize 1100 -#define EventWindowWillEnterFullScreen 1101 -#define EventWindowWillEnterVersionBrowser 1102 -#define EventWindowWillExitFullScreen 1103 -#define EventWindowWillExitVersionBrowser 1104 -#define EventWindowWillFocus 1105 -#define EventWindowWillMiniaturize 1106 -#define EventWindowWillMove 1107 -#define EventWindowWillOrderOffScreen 1108 -#define EventWindowWillOrderOnScreen 1109 -#define EventWindowWillResignMain 1110 -#define EventWindowWillResize 1111 -#define EventWindowWillUnfocus 1112 -#define EventWindowWillUpdate 1113 -#define EventWindowWillUpdateAlpha 1114 -#define EventWindowWillUpdateCollectionBehavior 1115 -#define EventWindowWillUpdateCollectionProperties 1116 -#define EventWindowWillUpdateShadow 1117 -#define EventWindowWillUpdateTitle 1118 -#define EventWindowWillUpdateToolbar 1119 -#define EventWindowWillUpdateVisibility 1120 -#define EventWindowWillUseStandardFrame 1121 -#define EventMenuWillOpen 1122 -#define EventMenuDidOpen 1123 -#define EventMenuDidClose 1124 -#define EventMenuWillSendAction 1125 -#define EventMenuDidSendAction 1126 -#define EventMenuWillHighlightItem 1127 -#define EventMenuDidHighlightItem 1128 -#define EventMenuWillDisplayItem 1129 -#define EventMenuDidDisplayItem 1130 -#define EventMenuWillAddItem 1131 -#define EventMenuDidAddItem 1132 -#define EventMenuWillRemoveItem 1133 -#define EventMenuDidRemoveItem 1134 -#define EventMenuWillBeginTracking 1135 -#define EventMenuDidBeginTracking 1136 -#define EventMenuWillEndTracking 1137 -#define EventMenuDidEndTracking 1138 -#define EventMenuWillUpdate 1139 -#define EventMenuDidUpdate 1140 -#define EventMenuWillPopUp 1141 -#define EventMenuDidPopUp 1142 -#define EventMenuWillSendActionToItem 1143 -#define EventMenuDidSendActionToItem 1144 -#define EventWebViewDidStartProvisionalNavigation 1145 -#define EventWebViewDidReceiveServerRedirectForProvisionalNavigation 1146 -#define EventWebViewDidFinishNavigation 1147 -#define EventWebViewDidCommitNavigation 1148 -#define EventWindowFileDraggingEntered 1149 -#define EventWindowFileDraggingPerformed 1150 -#define EventWindowFileDraggingExited 1151 +#define EventApplicationDidBecomeActive 1030 +#define EventApplicationDidChangeBackingProperties 1031 +#define EventApplicationDidChangeEffectiveAppearance 1032 +#define EventApplicationDidChangeIcon 1033 +#define EventApplicationDidChangeOcclusionState 1034 +#define EventApplicationDidChangeScreenParameters 1035 +#define EventApplicationDidChangeStatusBarFrame 1036 +#define EventApplicationDidChangeStatusBarOrientation 1037 +#define EventApplicationDidFinishLaunching 1038 +#define EventApplicationDidHide 1039 +#define EventApplicationDidResignActiveNotification 1040 +#define EventApplicationDidUnhide 1041 +#define EventApplicationDidUpdate 1042 +#define EventApplicationWillBecomeActive 1043 +#define EventApplicationWillFinishLaunching 1044 +#define EventApplicationWillHide 1045 +#define EventApplicationWillResignActive 1046 +#define EventApplicationWillTerminate 1047 +#define EventApplicationWillUnhide 1048 +#define EventApplicationWillUpdate 1049 +#define EventApplicationDidChangeTheme 1050 +#define EventApplicationShouldHandleReopen 1051 +#define EventWindowDidBecomeKey 1052 +#define EventWindowDidBecomeMain 1053 +#define EventWindowDidBeginSheet 1054 +#define EventWindowDidChangeAlpha 1055 +#define EventWindowDidChangeBackingLocation 1056 +#define EventWindowDidChangeBackingProperties 1057 +#define EventWindowDidChangeCollectionBehavior 1058 +#define EventWindowDidChangeEffectiveAppearance 1059 +#define EventWindowDidChangeOcclusionState 1060 +#define EventWindowDidChangeOrderingMode 1061 +#define EventWindowDidChangeScreen 1062 +#define EventWindowDidChangeScreenParameters 1063 +#define EventWindowDidChangeScreenProfile 1064 +#define EventWindowDidChangeScreenSpace 1065 +#define EventWindowDidChangeScreenSpaceProperties 1066 +#define EventWindowDidChangeSharingType 1067 +#define EventWindowDidChangeSpace 1068 +#define EventWindowDidChangeSpaceOrderingMode 1069 +#define EventWindowDidChangeTitle 1070 +#define EventWindowDidChangeToolbar 1071 +#define EventWindowDidChangeVisibility 1072 +#define EventWindowDidDeminiaturize 1073 +#define EventWindowDidEndSheet 1074 +#define EventWindowDidEnterFullScreen 1075 +#define EventWindowDidEnterVersionBrowser 1076 +#define EventWindowDidExitFullScreen 1077 +#define EventWindowDidExitVersionBrowser 1078 +#define EventWindowDidExpose 1079 +#define EventWindowDidFocus 1080 +#define EventWindowDidMiniaturize 1081 +#define EventWindowDidMove 1082 +#define EventWindowDidOrderOffScreen 1083 +#define EventWindowDidOrderOnScreen 1084 +#define EventWindowDidResignKey 1085 +#define EventWindowDidResignMain 1086 +#define EventWindowDidResize 1087 +#define EventWindowDidUpdate 1088 +#define EventWindowDidUpdateAlpha 1089 +#define EventWindowDidUpdateCollectionBehavior 1090 +#define EventWindowDidUpdateCollectionProperties 1091 +#define EventWindowDidUpdateShadow 1092 +#define EventWindowDidUpdateTitle 1093 +#define EventWindowDidUpdateToolbar 1094 +#define EventWindowDidUpdateVisibility 1095 +#define EventWindowShouldClose 1096 +#define EventWindowWillBecomeKey 1097 +#define EventWindowWillBecomeMain 1098 +#define EventWindowWillBeginSheet 1099 +#define EventWindowWillChangeOrderingMode 1100 +#define EventWindowWillClose 1101 +#define EventWindowWillDeminiaturize 1102 +#define EventWindowWillEnterFullScreen 1103 +#define EventWindowWillEnterVersionBrowser 1104 +#define EventWindowWillExitFullScreen 1105 +#define EventWindowWillExitVersionBrowser 1106 +#define EventWindowWillFocus 1107 +#define EventWindowWillMiniaturize 1108 +#define EventWindowWillMove 1109 +#define EventWindowWillOrderOffScreen 1110 +#define EventWindowWillOrderOnScreen 1111 +#define EventWindowWillResignMain 1112 +#define EventWindowWillResize 1113 +#define EventWindowWillUnfocus 1114 +#define EventWindowWillUpdate 1115 +#define EventWindowWillUpdateAlpha 1116 +#define EventWindowWillUpdateCollectionBehavior 1117 +#define EventWindowWillUpdateCollectionProperties 1118 +#define EventWindowWillUpdateShadow 1119 +#define EventWindowWillUpdateTitle 1120 +#define EventWindowWillUpdateToolbar 1121 +#define EventWindowWillUpdateVisibility 1122 +#define EventWindowWillUseStandardFrame 1123 +#define EventMenuWillOpen 1124 +#define EventMenuDidOpen 1125 +#define EventMenuDidClose 1126 +#define EventMenuWillSendAction 1127 +#define EventMenuDidSendAction 1128 +#define EventMenuWillHighlightItem 1129 +#define EventMenuDidHighlightItem 1130 +#define EventMenuWillDisplayItem 1131 +#define EventMenuDidDisplayItem 1132 +#define EventMenuWillAddItem 1133 +#define EventMenuDidAddItem 1134 +#define EventMenuWillRemoveItem 1135 +#define EventMenuDidRemoveItem 1136 +#define EventMenuWillBeginTracking 1137 +#define EventMenuDidBeginTracking 1138 +#define EventMenuWillEndTracking 1139 +#define EventMenuDidEndTracking 1140 +#define EventMenuWillUpdate 1141 +#define EventMenuDidUpdate 1142 +#define EventMenuWillPopUp 1143 +#define EventMenuDidPopUp 1144 +#define EventMenuWillSendActionToItem 1145 +#define EventMenuDidSendActionToItem 1146 +#define EventWebViewDidStartProvisionalNavigation 1147 +#define EventWebViewDidReceiveServerRedirectForProvisionalNavigation 1148 +#define EventWebViewDidFinishNavigation 1149 +#define EventWebViewDidCommitNavigation 1150 +#define EventWindowFileDraggingEntered 1151 +#define EventWindowFileDraggingPerformed 1152 +#define EventWindowFileDraggingExited 1153 -#define MAX_EVENTS 1152 +#define MAX_EVENTS 1154 #endif \ No newline at end of file diff --git a/v3/pkg/events/events_linux.h b/v3/pkg/events/events_linux.h index 25409b5f04d..21b6f32eee0 100644 --- a/v3/pkg/events/events_linux.h +++ b/v3/pkg/events/events_linux.h @@ -9,9 +9,11 @@ extern void processWindowEvent(unsigned int, unsigned int); #define EventSystemThemeChanged 1024 #define EventWindowLoadChanged 1025 #define EventWindowDeleteEvent 1026 -#define EventApplicationStartup 1027 +#define EventWindowFocusIn 1027 +#define EventWindowFocusOut 1028 +#define EventApplicationStartup 1029 -#define MAX_EVENTS 1028 +#define MAX_EVENTS 1030 #endif \ No newline at end of file From 430736a4f2f18ddd0fb7ab4a9e8c2716c65472f2 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 13 Feb 2024 20:56:19 +1100 Subject: [PATCH 073/369] Remove need for javascriptcore --- v3/internal/operatingsystem/webkit_linux.go | 2 +- v3/pkg/application/linux_cgo.go | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/v3/internal/operatingsystem/webkit_linux.go b/v3/internal/operatingsystem/webkit_linux.go index 70085d8fa1b..a13f6eebfdf 100644 --- a/v3/internal/operatingsystem/webkit_linux.go +++ b/v3/internal/operatingsystem/webkit_linux.go @@ -1,7 +1,7 @@ package operatingsystem /* -#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 javascriptcoregtk-4.1 +#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 #include */ import "C" diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index df8eff50e72..2c4650764e3 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -14,9 +14,8 @@ import ( ) /* -#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 javascriptcoregtk-4.1 gdk-3.0 +#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 gdk-3.0 -#include #include #include #include From ab9eec12eb4cddc7627442592cf58c949c5f4bc0 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 13 Feb 2024 21:12:24 +1100 Subject: [PATCH 074/369] Update status. Make wml demo non-drag --- mkdocs-website/shared/alpha5.csv | 32 +++++++++++++++---------------- v3/examples/wml/assets/index.html | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/mkdocs-website/shared/alpha5.csv b/mkdocs-website/shared/alpha5.csv index f372dc65f02..4fc242c516c 100644 --- a/mkdocs-website/shared/alpha5.csv +++ b/mkdocs-website/shared/alpha5.csv @@ -1,16 +1,16 @@ -" ",Mac,Windows,Linux -binding,:material-check-bold:,:material-check-bold:,:material-check-bold: -build,:material-check-bold:,:material-check-bold:,:material-check-bold: -clipboard,:material-check-bold:,:material-check-bold:,:material-check-bold: -context menus,:material-check-bold:,:material-check-bold:,:material-check-bold: -dialogs,:material-check-bold:,:material-check-bold:,:material-check-bold: -drag-n-drop,:material-check-bold:,:material-check-bold:,:material-check-bold: -events,:material-check-bold:,:material-check-bold:,:material-minus: -frameless,:material-check-bold:,:material-check-bold:,:material-check-bold: -keybindings,:material-check-bold:,:material-check-bold:,:material-minus: -plain,:material-check-bold:,:material-check-bold:,:material-check-bold: -screen,:material-check-bold:,:material-check-bold:,:material-check-bold: -systray,:material-check-bold:,:material-check-bold:,:material-check-bold: -video,:material-check-bold:,:material-check-bold:,:material-check-bold: -window,:material-check-bold:,:material-check-bold:,:material-minus: -wml,:material-check-bold:,:material-check-bold:,:material-check-bold: \ No newline at end of file +Example,Linux +binding," " +build," " +clipboard,:material-check-bold: +context menus," " +dialogs," " +drag-n-drop," " +events,:material-check-bold: +frameless," " +keybindings," " +plain," " +screen," " +systray,:material-check-bold: +video," " +window,:material-check-bold: +wml,:material-check-bold: \ No newline at end of file diff --git a/v3/examples/wml/assets/index.html b/v3/examples/wml/assets/index.html index 1dca07b22bc..bd5c61f8e8d 100644 --- a/v3/examples/wml/assets/index.html +++ b/v3/examples/wml/assets/index.html @@ -131,7 +131,7 @@ - +
Alpha
From 065ca5f6d34e3e0587f71590c6974a3dd7179cf8 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Wed, 14 Feb 2024 21:09:12 +1100 Subject: [PATCH 075/369] Move to latest webkit2 and remove older code. Fix screen demo. Update examples. --- mkdocs-website/shared/alpha5.csv | 8 +- v3/examples/contextmenus/assets/index.html | 2 +- v3/examples/contextmenus/assets/runtime.js | 1 + v3/examples/frameless/assets/runtime.js | 2 +- v3/examples/frameless/go.sum | 10 +- v3/examples/keybindings/main.go | 2 +- v3/examples/screen/assets/index.html | 1 + v3/examples/screen/assets/runtime.js | 1 + v3/examples/video/go.mod | 14 +- v3/examples/video/go.sum | 168 ++++++++++-------- v3/examples/wml/assets/runtime.js | 2 +- .../webview/{webkit2_36+.go => webkit2.go} | 70 +++++++- v3/internal/assetserver/webview/webkit2_36.go | 21 --- .../assetserver/webview/webkit2_40+.go | 83 --------- .../assetserver/webview/webkit2_40+_purego.go | 74 -------- v3/internal/assetserver/webview/webkit2_40.go | 5 - .../assetserver/webview/webkit2_legacy.go | 48 ----- .../webview/webkit2_legacy_purego.go | 36 ---- ...ebkit2_36+_purego.go => webkit2_purego.go} | 66 ++++++- .../build_assets/runtime/runtime.debug.js | 9 +- .../commands/build_assets/runtime/runtime.js | 2 +- v3/internal/runtime/Taskfile.yaml | 2 + v3/pkg/application/assets/alpha/runtime.js | 2 +- 23 files changed, 259 insertions(+), 370 deletions(-) create mode 100644 v3/examples/contextmenus/assets/runtime.js create mode 100644 v3/examples/screen/assets/runtime.js rename v3/internal/assetserver/webview/{webkit2_36+.go => webkit2.go} (53%) delete mode 100644 v3/internal/assetserver/webview/webkit2_36.go delete mode 100644 v3/internal/assetserver/webview/webkit2_40+.go delete mode 100644 v3/internal/assetserver/webview/webkit2_40+_purego.go delete mode 100644 v3/internal/assetserver/webview/webkit2_40.go delete mode 100644 v3/internal/assetserver/webview/webkit2_legacy.go delete mode 100644 v3/internal/assetserver/webview/webkit2_legacy_purego.go rename v3/internal/assetserver/webview/{webkit2_36+_purego.go => webkit2_purego.go} (62%) diff --git a/mkdocs-website/shared/alpha5.csv b/mkdocs-website/shared/alpha5.csv index 4fc242c516c..158b6a0c7cf 100644 --- a/mkdocs-website/shared/alpha5.csv +++ b/mkdocs-website/shared/alpha5.csv @@ -6,11 +6,11 @@ context menus," " dialogs," " drag-n-drop," " events,:material-check-bold: -frameless," " -keybindings," " +frameless,:material-check-bold: +keybindings,:material-check-bold: plain," " -screen," " +screen,:material-check-bold: systray,:material-check-bold: -video," " +video,:material-check-bold: window,:material-check-bold: wml,:material-check-bold: \ No newline at end of file diff --git a/v3/examples/contextmenus/assets/index.html b/v3/examples/contextmenus/assets/index.html index db6721e39d9..0c1c5e110aa 100644 --- a/v3/examples/contextmenus/assets/index.html +++ b/v3/examples/contextmenus/assets/index.html @@ -3,7 +3,7 @@ Title - + diff --git a/v3/examples/contextmenus/assets/runtime.js b/v3/examples/contextmenus/assets/runtime.js new file mode 100644 index 00000000000..baaccee0402 --- /dev/null +++ b/v3/examples/contextmenus/assets/runtime.js @@ -0,0 +1 @@ +(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return q(Ce,{text:e})}function Me(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/examples/frameless/assets/runtime.js b/v3/examples/frameless/assets/runtime.js index 2c7d16ed30b..baaccee0402 100644 --- a/v3/examples/frameless/assets/runtime.js +++ b/v3/examples/frameless/assets/runtime.js @@ -1 +1 @@ -(()=>{var le=Object.defineProperty;var w=(e,i)=>{for(var n in i)le(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var de="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=de[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",l={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9,CancelCall:10},se=f();function d(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,m)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();m(Error(c.statusText))}).then(c=>s(c)).catch(c=>m(c))})}var P=d(l.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=d(l.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>Me,Text:()=>xe});var Q=d(l.Clipboard,""),Ce=0,Se=1;function Me(e){return Q(Ce,{text:e})}function xe(){return Q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=d(l.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=d(l.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var M=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",M=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(M=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function W(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){M=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return M&&i>0?(h("drag"),!1):M}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=d(l.Screens,""),Xe=0,qe=1,Qe=2;function Je(){return k(Xe)}function $e(){return k(qe)}function ei(){return k(Qe)}var H={};w(H,{Center:()=>Oi,Close:()=>qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>Qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,li=6,di=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,Mi=21,xi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(d(l.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(li,{width:i,height:n}),SetMinSize:(i,n)=>e(di,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(Mi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(xi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(d(l.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function qi(){r.Close()}function Qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>ln,WailsEvent:()=>x,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var ln=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var dn=d(l.Events,""),cn=0,u=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},x=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=u.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?u.delete(e.name):u.set(e.name,i))}}function _(e,i,n){let o=u.get(e)||[],t=new V(e,i,n);return o.push(t),u.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=u.get(i).filter(o=>o!==e);n.length===0?u.delete(i):u.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>u.delete(o))}function gn(){u.clear()}function Z(e){return dn(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,Mn=5,xn=d(l.Dialog,""),g=new Map;function An(){let e;do e=f();while(g.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{g.set(n,{resolve:o,reject:t}),xn(e,i).catch(a=>{t(a),g.delete(n)})})}function vn(e,i,n){let o=g.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),g.delete(e))}function bn(e,i){let n=g.get(e);n&&(n.reject(i),g.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(Mn,e);function oe(e,i=null){let n=new x(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(m){m!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>_n,ByName:()=>Vn,Call:()=>Hn,Plugin:()=>Zn});window._wails=window._wails||{};window._wails.callResultHandler=kn;window._wails.callErrorHandler=Nn;var y=0,Fn=d(l.Call,""),Ln=d(l.CancelCall,""),v=new Map;function zn(){let e;do e=f();while(v.has(e));return e}function kn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function Nn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){let n=zn(),o=()=>{Ln(e,{"call-id":n})};var t=!1,a=!1,s=new Promise((m,c)=>{i["call-id"]=n,v.set(n,{resolve:m,reject:c}),Fn(e,i).then(p=>{a=!0,t&&o()}).catch(p=>{c(p),v.delete(n)})});return s.cancel=()=>{a?o():t=!0},s}function Hn(e){return O(y,e)}function Vn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function _n(e,...i){return O(y,{methodID:e,args:i})}function Zn(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function jn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}jn(()=>{Y()});})(); +(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return q(Ce,{text:e})}function Me(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/examples/frameless/go.sum b/v3/examples/frameless/go.sum index 1b0b965ca4f..476b71ea3bd 100644 --- a/v3/examples/frameless/go.sum +++ b/v3/examples/frameless/go.sum @@ -110,8 +110,7 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= @@ -151,16 +150,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/v3/examples/keybindings/main.go b/v3/examples/keybindings/main.go index a78068ac29a..ee9dee82568 100644 --- a/v3/examples/keybindings/main.go +++ b/v3/examples/keybindings/main.go @@ -26,7 +26,7 @@ func main() { URL: "https://wails.io", KeyBindings: map[string]func(window *application.WebviewWindow){ "F12": func(window *application.WebviewWindow) { - window.ToggleDevTools() + window.OpenDevTools() }, }, }) diff --git a/v3/examples/screen/assets/index.html b/v3/examples/screen/assets/index.html index 4b385ada1fd..eafcfe1b9c2 100644 --- a/v3/examples/screen/assets/index.html +++ b/v3/examples/screen/assets/index.html @@ -43,6 +43,7 @@ text-align: -webkit-center; } + diff --git a/v3/examples/screen/assets/runtime.js b/v3/examples/screen/assets/runtime.js new file mode 100644 index 00000000000..baaccee0402 --- /dev/null +++ b/v3/examples/screen/assets/runtime.js @@ -0,0 +1 @@ +(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return q(Ce,{text:e})}function Me(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/examples/video/go.mod b/v3/examples/video/go.mod index 525e941b491..fed31b83339 100644 --- a/v3/examples/video/go.mod +++ b/v3/examples/video/go.mod @@ -7,8 +7,12 @@ toolchain go1.22.0 require github.com/wailsapp/wails/v3 v3.0.0-alpha.0 require ( + dario.cat/mergo v1.0.0 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/bep/debounce v1.2.1 // indirect + github.com/cloudflare/circl v1.3.3 // indirect + github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/ebitengine/purego v0.4.0-alpha.4 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect @@ -16,31 +20,31 @@ require ( github.com/go-git/go-git/v5 v5.11.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/uuid v1.3.0 // indirect - github.com/imdario/mergo v0.3.12 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect - github.com/json-iterator/go v1.1.12 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/leaanthony/go-ansi-parser v1.6.1 // indirect github.com/leaanthony/u v1.1.0 // indirect github.com/lmittmann/tint v1.0.3 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/samber/lo v1.38.1 // indirect github.com/sergi/go-diff v1.2.0 // indirect + github.com/skeema/knownhosts v1.2.1 // indirect github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect + golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.19.0 // indirect golang.org/x/sys v0.17.0 // indirect + golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/video/go.sum b/v3/examples/video/go.sum index f59a0e5caef..476b71ea3bd 100644 --- a/v3/examples/video/go.sum +++ b/v3/examples/video/go.sum @@ -1,67 +1,59 @@ -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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/ebitengine/purego v0.4.0-alpha.4 h1:Y7yIV06Yo5M2BAdD7EVPhfp6LZ0tEcQo5770OhYUVes= github.com/ebitengine/purego v0.4.0-alpha.4/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.2.0 h1:GcoouCP9J+5slw2uXAocL70z8ml4A8B/H8nEPt6CLPk= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= -github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= -github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= -github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc= -github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= +github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -70,8 +62,7 @@ github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI= github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/lmittmann/tint v1.0.0 h1:fzEj70K1L58uyoePQxKe+ezDZJ5pybiWGdA0JeFvvyw= -github.com/lmittmann/tint v1.0.0/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= +github.com/lmittmann/tint v1.0.3 h1:W5PHeA2D8bBJVvabNfQD/XW9HPLZK1XoPZH0cq8NouQ= github.com/lmittmann/tint v1.0.3/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= @@ -80,16 +71,12 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -97,79 +84,104 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/wailsapp/go-webview2 v1.0.9 h1:lrU+q0cf1wgLdR69rN+ZnRtMJNaJRrcQ4ELxoO7/xjs= github.com/wailsapp/go-webview2 v1.0.9/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo= github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= -github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= -github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/examples/wml/assets/runtime.js b/v3/examples/wml/assets/runtime.js index 2c7d16ed30b..baaccee0402 100644 --- a/v3/examples/wml/assets/runtime.js +++ b/v3/examples/wml/assets/runtime.js @@ -1 +1 @@ -(()=>{var le=Object.defineProperty;var w=(e,i)=>{for(var n in i)le(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var de="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=de[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",l={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9,CancelCall:10},se=f();function d(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,m)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();m(Error(c.statusText))}).then(c=>s(c)).catch(c=>m(c))})}var P=d(l.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=d(l.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>Me,Text:()=>xe});var Q=d(l.Clipboard,""),Ce=0,Se=1;function Me(e){return Q(Ce,{text:e})}function xe(){return Q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=d(l.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=d(l.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var M=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",M=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(M=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function W(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){M=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return M&&i>0?(h("drag"),!1):M}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=d(l.Screens,""),Xe=0,qe=1,Qe=2;function Je(){return k(Xe)}function $e(){return k(qe)}function ei(){return k(Qe)}var H={};w(H,{Center:()=>Oi,Close:()=>qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>Qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,li=6,di=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,Mi=21,xi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(d(l.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(li,{width:i,height:n}),SetMinSize:(i,n)=>e(di,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(Mi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(xi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(d(l.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function qi(){r.Close()}function Qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>ln,WailsEvent:()=>x,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var ln=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var dn=d(l.Events,""),cn=0,u=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},x=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=u.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?u.delete(e.name):u.set(e.name,i))}}function _(e,i,n){let o=u.get(e)||[],t=new V(e,i,n);return o.push(t),u.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=u.get(i).filter(o=>o!==e);n.length===0?u.delete(i):u.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>u.delete(o))}function gn(){u.clear()}function Z(e){return dn(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,Mn=5,xn=d(l.Dialog,""),g=new Map;function An(){let e;do e=f();while(g.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{g.set(n,{resolve:o,reject:t}),xn(e,i).catch(a=>{t(a),g.delete(n)})})}function vn(e,i,n){let o=g.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),g.delete(e))}function bn(e,i){let n=g.get(e);n&&(n.reject(i),g.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(Mn,e);function oe(e,i=null){let n=new x(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(m){m!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>_n,ByName:()=>Vn,Call:()=>Hn,Plugin:()=>Zn});window._wails=window._wails||{};window._wails.callResultHandler=kn;window._wails.callErrorHandler=Nn;var y=0,Fn=d(l.Call,""),Ln=d(l.CancelCall,""),v=new Map;function zn(){let e;do e=f();while(v.has(e));return e}function kn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function Nn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){let n=zn(),o=()=>{Ln(e,{"call-id":n})};var t=!1,a=!1,s=new Promise((m,c)=>{i["call-id"]=n,v.set(n,{resolve:m,reject:c}),Fn(e,i).then(p=>{a=!0,t&&o()}).catch(p=>{c(p),v.delete(n)})});return s.cancel=()=>{a?o():t=!0},s}function Hn(e){return O(y,e)}function Vn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function _n(e,...i){return O(y,{methodID:e,args:i})}function Zn(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function jn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}jn(()=>{Y()});})(); +(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return q(Ce,{text:e})}function Me(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/internal/assetserver/webview/webkit2_36+.go b/v3/internal/assetserver/webview/webkit2.go similarity index 53% rename from v3/internal/assetserver/webview/webkit2_36+.go rename to v3/internal/assetserver/webview/webkit2.go index 2c1a79c4331..2682dc81f3a 100644 --- a/v3/internal/assetserver/webview/webkit2_36+.go +++ b/v3/internal/assetserver/webview/webkit2.go @@ -1,4 +1,4 @@ -//go:build linux && (webkit2_36 || webkit2_40) +//go:build linux package webview @@ -12,11 +12,15 @@ package webview import "C" import ( + "fmt" + "io" "net/http" "strings" "unsafe" ) +const Webkit2MinMinorVersion = 40 + func webkit_uri_scheme_request_get_http_method(req *C.WebKitURISchemeRequest) string { method := C.GoString(C.webkit_uri_scheme_request_get_http_method(req)) return strings.ToUpper(method) @@ -67,3 +71,67 @@ func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, h C.webkit_uri_scheme_request_finish_with_response(req, resp) return nil } + +func webkit_uri_scheme_request_get_http_body(req *C.WebKitURISchemeRequest) io.ReadCloser { + stream := C.webkit_uri_scheme_request_get_http_body(req) + if stream == nil { + return http.NoBody + } + return &webkitRequestBody{stream: stream} +} + +type webkitRequestBody struct { + stream *C.GInputStream + closed bool +} + +// Read implements io.Reader +func (r *webkitRequestBody) Read(p []byte) (int, error) { + if r.closed { + return 0, io.ErrClosedPipe + } + + var content unsafe.Pointer + var contentLen int + if p != nil { + content = unsafe.Pointer(&p[0]) + contentLen = len(p) + } + + var n C.gsize + var gErr *C.GError + res := C.g_input_stream_read_all(r.stream, content, C.gsize(contentLen), &n, nil, &gErr) + if res == 0 { + return 0, formatGError("stream read failed", gErr) + } else if n == 0 { + return 0, io.EOF + } + return int(n), nil +} + +func (r *webkitRequestBody) Close() error { + if r.closed { + return nil + } + r.closed = true + + // https://docs.gtk.org/gio/method.InputStream.close.html + // Streams will be automatically closed when the last reference is dropped, but you might want to call this function + // to make sure resources are released as early as possible. + var err error + var gErr *C.GError + if C.g_input_stream_close(r.stream, nil, &gErr) == 0 { + err = formatGError("stream close failed", gErr) + } + C.g_object_unref(C.gpointer(r.stream)) + r.stream = nil + return err +} + +func formatGError(msg string, gErr *C.GError, args ...any) error { + if gErr != nil && gErr.message != nil { + msg += ": " + C.GoString(gErr.message) + C.g_error_free(gErr) + } + return fmt.Errorf(msg, args...) +} diff --git a/v3/internal/assetserver/webview/webkit2_36.go b/v3/internal/assetserver/webview/webkit2_36.go deleted file mode 100644 index cd200af8eb6..00000000000 --- a/v3/internal/assetserver/webview/webkit2_36.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build linux && webkit2_36 - -package webview - -/* -#cgo linux pkg-config: webkit2gtk-4.0 - -#include "webkit2/webkit2.h" -*/ -import "C" - -import ( - "io" - "net/http" -) - -const Webkit2MinMinorVersion = 36 - -func webkit_uri_scheme_request_get_http_body(_ *C.WebKitURISchemeRequest) io.ReadCloser { - return http.NoBody -} diff --git a/v3/internal/assetserver/webview/webkit2_40+.go b/v3/internal/assetserver/webview/webkit2_40+.go deleted file mode 100644 index dceb0803d5d..00000000000 --- a/v3/internal/assetserver/webview/webkit2_40+.go +++ /dev/null @@ -1,83 +0,0 @@ -//go:build linux && webkit2_40 - -package webview - -/* -#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 gio-unix-2.0 - -#include "gtk/gtk.h" -#include "webkit2/webkit2.h" -#include "gio/gunixinputstream.h" -*/ -import "C" - -import ( - "fmt" - "io" - "net/http" - "unsafe" -) - -func webkit_uri_scheme_request_get_http_body(req *C.WebKitURISchemeRequest) io.ReadCloser { - stream := C.webkit_uri_scheme_request_get_http_body(req) - if stream == nil { - return http.NoBody - } - return &webkitRequestBody{stream: stream} -} - -type webkitRequestBody struct { - stream *C.GInputStream - closed bool -} - -// Read implements io.Reader -func (r *webkitRequestBody) Read(p []byte) (int, error) { - if r.closed { - return 0, io.ErrClosedPipe - } - - var content unsafe.Pointer - var contentLen int - if p != nil { - content = unsafe.Pointer(&p[0]) - contentLen = len(p) - } - - var n C.gsize - var gErr *C.GError - res := C.g_input_stream_read_all(r.stream, content, C.gsize(contentLen), &n, nil, &gErr) - if res == 0 { - return 0, formatGError("stream read failed", gErr) - } else if n == 0 { - return 0, io.EOF - } - return int(n), nil -} - -func (r *webkitRequestBody) Close() error { - if r.closed { - return nil - } - r.closed = true - - // https://docs.gtk.org/gio/method.InputStream.close.html - // Streams will be automatically closed when the last reference is dropped, but you might want to call this function - // to make sure resources are released as early as possible. - var err error - var gErr *C.GError - if C.g_input_stream_close(r.stream, nil, &gErr) == 0 { - err = formatGError("stream close failed", gErr) - } - C.g_object_unref(C.gpointer(r.stream)) - r.stream = nil - return err -} - -func formatGError(msg string, gErr *C.GError, args ...any) error { - if gErr != nil && gErr.message != nil { - msg += ": " + C.GoString(gErr.message) - C.g_error_free(gErr) - } - return fmt.Errorf(msg, args...) -} diff --git a/v3/internal/assetserver/webview/webkit2_40+_purego.go b/v3/internal/assetserver/webview/webkit2_40+_purego.go deleted file mode 100644 index 1088be25e09..00000000000 --- a/v3/internal/assetserver/webview/webkit2_40+_purego.go +++ /dev/null @@ -1,74 +0,0 @@ -//go:build linux && webkit2_40 && purego - -package webview - -import ( - "fmt" - "io" - "net/http" - "unsafe" -) - -func webkit_uri_scheme_request_get_http_body(req *C.WebKitURISchemeRequest) io.ReadCloser { - stream := C.webkit_uri_scheme_request_get_http_body(req) - if stream == nil { - return http.NoBody - } - return &webkitRequestBody{stream: stream} -} - -type webkitRequestBody struct { - stream *C.GInputStream - closed bool -} - -// Read implements io.Reader -func (r *webkitRequestBody) Read(p []byte) (int, error) { - if r.closed { - return 0, io.ErrClosedPipe - } - - var content unsafe.Pointer - var contentLen int - if p != nil { - content = unsafe.Pointer(&p[0]) - contentLen = len(p) - } - - var n C.gsize - var gErr *C.GError - res := C.g_input_stream_read_all(r.stream, content, C.gsize(contentLen), &n, nil, &gErr) - if res == 0 { - return 0, formatGError("stream read failed", gErr) - } else if n == 0 { - return 0, io.EOF - } - return int(n), nil -} - -func (r *webkitRequestBody) Close() error { - if r.closed { - return nil - } - r.closed = true - - // https://docs.gtk.org/gio/method.InputStream.close.html - // Streams will be automatically closed when the last reference is dropped, but you might want to call this function - // to make sure resources are released as early as possible. - var err error - var gErr *C.GError - if C.g_input_stream_close(r.stream, nil, &gErr) == 0 { - err = formatGError("stream close failed", gErr) - } - C.g_object_unref(C.gpointer(r.stream)) - r.stream = nil - return err -} - -func formatGError(msg string, gErr *C.GError, args ...any) error { - if gErr != nil && gErr.message != nil { - msg += ": " + C.GoString(gErr.message) - C.g_error_free(gErr) - } - return fmt.Errorf(msg, args...) -} diff --git a/v3/internal/assetserver/webview/webkit2_40.go b/v3/internal/assetserver/webview/webkit2_40.go deleted file mode 100644 index 47b504383af..00000000000 --- a/v3/internal/assetserver/webview/webkit2_40.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build linux && webkit2_40 - -package webview - -const Webkit2MinMinorVersion = 40 diff --git a/v3/internal/assetserver/webview/webkit2_legacy.go b/v3/internal/assetserver/webview/webkit2_legacy.go deleted file mode 100644 index 1a87fe96aeb..00000000000 --- a/v3/internal/assetserver/webview/webkit2_legacy.go +++ /dev/null @@ -1,48 +0,0 @@ -//go:build linux && !(webkit2_36 || webkit2_40) - -package webview - -/* -#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 - -#include "gtk/gtk.h" -#include "webkit2/webkit2.h" -*/ -import "C" - -import ( - "fmt" - "io" - "net/http" - "unsafe" -) - -const Webkit2MinMinorVersion = 0 - -func webkit_uri_scheme_request_get_http_method(_ *C.WebKitURISchemeRequest) string { - return http.MethodGet -} - -func webkit_uri_scheme_request_get_http_headers(_ *C.WebKitURISchemeRequest) http.Header { - // Fake some basic default headers that are needed if e.g. request are being proxied to the an external sever, like - // we do in the devserver. - h := http.Header{} - h.Add("Accept", "*/*") - h.Add("User-Agent", "wails.io/605.1.15") - return h -} - -func webkit_uri_scheme_request_get_http_body(_ *C.WebKitURISchemeRequest) io.ReadCloser { - return http.NoBody -} - -func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, header http.Header, stream *C.GInputStream, streamLength int64) error { - if code != http.StatusOK { - return fmt.Errorf("StatusCodes not supported: %d - %s", code, http.StatusText(code)) - } - - cMimeType := C.CString(header.Get(HeaderContentType)) - C.webkit_uri_scheme_request_finish(req, stream, C.gint64(streamLength), cMimeType) - C.free(unsafe.Pointer(cMimeType)) - return nil -} diff --git a/v3/internal/assetserver/webview/webkit2_legacy_purego.go b/v3/internal/assetserver/webview/webkit2_legacy_purego.go deleted file mode 100644 index 2e88864c8e8..00000000000 --- a/v3/internal/assetserver/webview/webkit2_legacy_purego.go +++ /dev/null @@ -1,36 +0,0 @@ -//go:build linux && !(webkit2_36 || webkit2_40) && purego - -package webview - -import ( - "fmt" - "io" - "net/http" - - "github.com/ebitengine/purego" -) - -const Webkit2MinMinorVersion = 0 - -func webkit_uri_scheme_request_get_http_method(_ uintptr) string { - return http.MethodGet -} - -func webkit_uri_scheme_request_get_http_headers(_ uintptr) http.Header { - return http.Header{} -} - -func webkit_uri_scheme_request_get_http_body(_ uintptr) io.ReadCloser { - return http.NoBody -} - -func webkit_uri_scheme_request_finish(req uintptr, code int, header http.Header, stream uintptr, streamLength int64) error { - if code != http.StatusOK { - return fmt.Errorf("StatusCodes not supported: %d - %s", code, http.StatusText(code)) - } - - var requestFinish func(uintptr, uintptr, int64, string) - purego.RegisterLibFunc(&requestFinish, webkit, "webkit_uri_scheme_request_finish") - requestFinish(req, stream, streamLength, header.Get(HeaderContentType)) - return nil -} diff --git a/v3/internal/assetserver/webview/webkit2_36+_purego.go b/v3/internal/assetserver/webview/webkit2_purego.go similarity index 62% rename from v3/internal/assetserver/webview/webkit2_36+_purego.go rename to v3/internal/assetserver/webview/webkit2_purego.go index 2386868c38f..28832c8bd95 100644 --- a/v3/internal/assetserver/webview/webkit2_36+_purego.go +++ b/v3/internal/assetserver/webview/webkit2_purego.go @@ -1,4 +1,4 @@ -//go:build linux && (webkit2_36 || webkit2_40) && purego +//go:build linux && purego package webview @@ -92,3 +92,67 @@ func webkit_uri_scheme_request_finish(req uintptr, code int, header http.Header, return nil } + +func webkit_uri_scheme_request_get_http_body(req *C.WebKitURISchemeRequest) io.ReadCloser { + stream := C.webkit_uri_scheme_request_get_http_body(req) + if stream == nil { + return http.NoBody + } + return &webkitRequestBody{stream: stream} +} + +type webkitRequestBody struct { + stream *C.GInputStream + closed bool +} + +// Read implements io.Reader +func (r *webkitRequestBody) Read(p []byte) (int, error) { + if r.closed { + return 0, io.ErrClosedPipe + } + + var content unsafe.Pointer + var contentLen int + if p != nil { + content = unsafe.Pointer(&p[0]) + contentLen = len(p) + } + + var n C.gsize + var gErr *C.GError + res := C.g_input_stream_read_all(r.stream, content, C.gsize(contentLen), &n, nil, &gErr) + if res == 0 { + return 0, formatGError("stream read failed", gErr) + } else if n == 0 { + return 0, io.EOF + } + return int(n), nil +} + +func (r *webkitRequestBody) Close() error { + if r.closed { + return nil + } + r.closed = true + + // https://docs.gtk.org/gio/method.InputStream.close.html + // Streams will be automatically closed when the last reference is dropped, but you might want to call this function + // to make sure resources are released as early as possible. + var err error + var gErr *C.GError + if C.g_input_stream_close(r.stream, nil, &gErr) == 0 { + err = formatGError("stream close failed", gErr) + } + C.g_object_unref(C.gpointer(r.stream)) + r.stream = nil + return err +} + +func formatGError(msg string, gErr *C.GError, args ...any) error { + if gErr != nil && gErr.message != nil { + msg += ": " + C.GoString(gErr.message) + C.g_error_free(gErr) + } + return fmt.Errorf(msg, args...) +} diff --git a/v3/internal/commands/build_assets/runtime/runtime.debug.js b/v3/internal/commands/build_assets/runtime/runtime.debug.js index cd19505891a..834309aac4c 100644 --- a/v3/internal/commands/build_assets/runtime/runtime.debug.js +++ b/v3/internal/commands/build_assets/runtime/runtime.debug.js @@ -736,7 +736,12 @@ WindowFileDraggingExited: "mac:WindowFileDraggingExited" }, Linux: { - SystemThemeChanged: "linux:SystemThemeChanged" + SystemThemeChanged: "linux:SystemThemeChanged", + WindowLoadChanged: "linux:WindowLoadChanged", + WindowDeleteEvent: "linux:WindowDeleteEvent", + WindowFocusIn: "linux:WindowFocusIn", + WindowFocusOut: "linux:WindowFocusOut", + ApplicationStartup: "linux:ApplicationStartup" }, Common: { ApplicationStarted: "common:ApplicationStarted", @@ -1131,4 +1136,4 @@ Reload(); }); })(); -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb24uanMiLCAiLi4vLi4vLi4vcnVudGltZS9ub2RlX21vZHVsZXMvbmFub2lkL25vbi1zZWN1cmUvaW5kZXguanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3J1bnRpbWUuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXIuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZC5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvc3lzdGVtLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jb250ZXh0bWVudS5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3MuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RyYWcuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3NjcmVlbnMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dpbmRvdy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvd21sLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9ldmVudHMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50X3R5cGVzLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9kaWFsb2dzLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxscy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvY29tcGlsZWQvbWFpbi5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBMb2dzIGEgbWVzc2FnZSB0byB0aGUgY29uc29sZSB3aXRoIGN1c3RvbSBmb3JtYXR0aW5nLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVidWdMb2cobWVzc2FnZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAnJWMgd2FpbHMzICVjICcgKyBtZXNzYWdlICsgJyAnLFxuICAgICAgICAnYmFja2dyb3VuZDogI2FhMDAwMDsgY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDNweCAwcHggMHB4IDNweDsgcGFkZGluZzogMXB4OyBmb250LXNpemU6IDAuN3JlbScsXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjMDA5OTAwOyBjb2xvcjogI2ZmZjsgYm9yZGVyLXJhZGl1czogMHB4IDNweCAzcHggMHB4OyBwYWRkaW5nOiAxcHg7IGZvbnQtc2l6ZTogMC43cmVtJ1xuICAgICk7XG59IiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZVwiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQXBwbGljYXRpb24sICcnKTtcblxuY29uc3QgSGlkZU1ldGhvZCA9IDA7XG5jb25zdCBTaG93TWV0aG9kID0gMTtcbmNvbnN0IFF1aXRNZXRob2QgPSAyO1xuXG4vKipcbiAqIEhpZGVzIGEgY2VydGFpbiBtZXRob2QgYnkgY2FsbGluZyB0aGUgSGlkZU1ldGhvZCBmdW5jdGlvbi5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XG4gICAgcmV0dXJuIGNhbGwoSGlkZU1ldGhvZCk7XG59XG5cbi8qKlxuICogQ2FsbHMgdGhlIFNob3dNZXRob2QgYW5kIHJldHVybnMgdGhlIHJlc3VsdC5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpIHtcbiAgICByZXR1cm4gY2FsbChTaG93TWV0aG9kKTtcbn1cblxuLyoqXG4gKiBDYWxscyB0aGUgUXVpdE1ldGhvZCB0byB0ZXJtaW5hdGUgdGhlIHByb2dyYW0uXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFF1aXQoKSB7XG4gICAgcmV0dXJuIGNhbGwoUXVpdE1ldGhvZCk7XG59XG4iLCAibGV0IHVybEFscGhhYmV0ID1cbiAgJ3VzZWFuZG9tLTI2VDE5ODM0MFBYNzVweEpBQ0tWRVJZTUlOREJVU0hXT0xGX0dRWmJmZ2hqa2xxdnd5enJpY3QnXG5leHBvcnQgbGV0IGN1c3RvbUFscGhhYmV0ID0gKGFscGhhYmV0LCBkZWZhdWx0U2l6ZSA9IDIxKSA9PiB7XG4gIHJldHVybiAoc2l6ZSA9IGRlZmF1bHRTaXplKSA9PiB7XG4gICAgbGV0IGlkID0gJydcbiAgICBsZXQgaSA9IHNpemVcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICBpZCArPSBhbHBoYWJldFsoTWF0aC5yYW5kb20oKSAqIGFscGhhYmV0Lmxlbmd0aCkgfCAwXVxuICAgIH1cbiAgICByZXR1cm4gaWRcbiAgfVxufVxuZXhwb3J0IGxldCBuYW5vaWQgPSAoc2l6ZSA9IDIxKSA9PiB7XG4gIGxldCBpZCA9ICcnXG4gIGxldCBpID0gc2l6ZVxuICB3aGlsZSAoaS0tKSB7XG4gICAgaWQgKz0gdXJsQWxwaGFiZXRbKE1hdGgucmFuZG9tKCkgKiA2NCkgfCAwXVxuICB9XG4gIHJldHVybiBpZFxufVxuIiwgIi8qXG4gXyAgICAgX18gICAgIF8gX19cbnwgfCAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQgeyBuYW5vaWQgfSBmcm9tICduYW5vaWQvbm9uLXNlY3VyZSc7XG5cbmNvbnN0IHJ1bnRpbWVVUkwgPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luICsgXCIvd2FpbHMvcnVudGltZVwiO1xuXG4vLyBPYmplY3QgTmFtZXNcbmV4cG9ydCBjb25zdCBvYmplY3ROYW1lcyA9IHtcbiAgICBDYWxsOiAwLFxuICAgIENsaXBib2FyZDogMSxcbiAgICBBcHBsaWNhdGlvbjogMixcbiAgICBFdmVudHM6IDMsXG4gICAgQ29udGV4dE1lbnU6IDQsXG4gICAgRGlhbG9nOiA1LFxuICAgIFdpbmRvdzogNixcbiAgICBTY3JlZW5zOiA3LFxuICAgIFN5c3RlbTogOCxcbiAgICBCcm93c2VyOiA5LFxuICAgIENhbmNlbENhbGw6IDEwLFxufVxuZXhwb3J0IGxldCBjbGllbnRJZCA9IG5hbm9pZCgpO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBydW50aW1lIGNhbGxlciBmdW5jdGlvbiB0aGF0IGludm9rZXMgYSBzcGVjaWZpZWQgbWV0aG9kIG9uIGEgZ2l2ZW4gb2JqZWN0IHdpdGhpbiBhIHNwZWNpZmllZCB3aW5kb3cgY29udGV4dC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IC0gVGhlIG9iamVjdCBvbiB3aGljaCB0aGUgbWV0aG9kIGlzIHRvIGJlIGludm9rZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgY29udGV4dCBpbiB3aGljaCB0aGUgbWV0aG9kIHNob3VsZCBiZSBjYWxsZWQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IEEgcnVudGltZSBjYWxsZXIgZnVuY3Rpb24gdGhhdCB0YWtlcyB0aGUgbWV0aG9kIG5hbWUgYW5kIG9wdGlvbmFsbHkgYXJndW1lbnRzIGFuZCBpbnZva2VzIHRoZSBtZXRob2Qgd2l0aGluIHRoZSBzcGVjaWZpZWQgd2luZG93IGNvbnRleHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdCwgd2luZG93TmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAobWV0aG9kLCBhcmdzPW51bGwpIHtcbiAgICAgICAgcmV0dXJuIHJ1bnRpbWVDYWxsKG9iamVjdCArIFwiLlwiICsgbWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKTtcbiAgICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcnVudGltZSBjYWxsZXIgd2l0aCBzcGVjaWZpZWQgSUQuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3QgdG8gaW52b2tlIHRoZSBtZXRob2Qgb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cuXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gLSBUaGUgbmV3IHJ1bnRpbWUgY2FsbGVyIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3QsIHdpbmRvd05hbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG1ldGhvZCwgYXJncz1udWxsKSB7XG4gICAgICAgIHJldHVybiBydW50aW1lQ2FsbFdpdGhJRChvYmplY3QsIG1ldGhvZCwgd2luZG93TmFtZSwgYXJncyk7XG4gICAgfTtcbn1cblxuXG5mdW5jdGlvbiBydW50aW1lQ2FsbChtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcbiAgICBpZiggbWV0aG9kICkge1xuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcIm1ldGhvZFwiLCBtZXRob2QpO1xuICAgIH1cbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICB9O1xuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuICAgIGlmIChhcmdzKSB7XG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiYXJnc1wiLCBKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgfVxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGZldGNoKHVybCwgZmV0Y2hPcHRpb25zKVxuICAgICAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayBjb250ZW50IHR5cGVcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpICYmIHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpLmluZGV4T2YoXCJhcHBsaWNhdGlvbi9qc29uXCIpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKHJlc3BvbnNlLnN0YXR1c1RleHQpKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbihkYXRhID0+IHJlc29sdmUoZGF0YSkpXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHJ1bnRpbWVDYWxsV2l0aElEKG9iamVjdElELCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcbiAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcIm9iamVjdFwiLCBvYmplY3RJRCk7XG4gICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJtZXRob2RcIiwgbWV0aG9kKTtcbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICB9O1xuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuICAgIGlmIChhcmdzKSB7XG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiYXJnc1wiLCBKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgfVxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBmZXRjaCh1cmwsIGZldGNoT3B0aW9ucylcbiAgICAgICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgY29udGVudCB0eXBlXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKSAmJiByZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKS5pbmRleE9mKFwiYXBwbGljYXRpb24vanNvblwiKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcihyZXNwb25zZS5zdGF0dXNUZXh0KSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oZGF0YSA9PiByZXNvbHZlKGRhdGEpKVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgIH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkJyb3dzZXIsICcnKTtcbmNvbnN0IEJyb3dzZXJPcGVuVVJMID0gMDtcblxuLyoqXG4gKiBPcGVuIGEgYnJvd3NlciB3aW5kb3cgdG8gdGhlIGdpdmVuIFVSTFxuICogQHBhcmFtIHtzdHJpbmd9IHVybCAtIFRoZSBVUkwgdG8gb3BlblxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9wZW5VUkwodXJsKSB7XG4gICAgcmV0dXJuIGNhbGwoQnJvd3Nlck9wZW5VUkwsIHt1cmx9KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkNsaXBib2FyZCwgJycpO1xuY29uc3QgQ2xpcGJvYXJkU2V0VGV4dCA9IDA7XG5jb25zdCBDbGlwYm9hcmRUZXh0ID0gMTtcblxuLyoqXG4gKiBTZXRzIHRoZSB0ZXh0IHRvIHRoZSBDbGlwYm9hcmQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgdGV4dCB0byBiZSBzZXQgdG8gdGhlIENsaXBib2FyZC5cbiAqIEByZXR1cm4ge1Byb21pc2V9IC0gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIHN1Y2Nlc3NmdWwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRUZXh0KHRleHQpIHtcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRTZXRUZXh0LCB7dGV4dH0pO1xufVxuXG4vKipcbiAqIEdldCB0aGUgQ2xpcGJvYXJkIHRleHRcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHRleHQgZnJvbSB0aGUgQ2xpcGJvYXJkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gVGV4dCgpIHtcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRUZXh0KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5sZXQgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU3lzdGVtLCAnJyk7XG5jb25zdCBzeXN0ZW1Jc0RhcmtNb2RlID0gMDtcbmNvbnN0IGVudmlyb25tZW50ID0gMTtcblxuZXhwb3J0IGZ1bmN0aW9uIGludm9rZShtc2cpIHtcbiAgICBpZih3aW5kb3cuY2hyb21lKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuY2hyb21lLndlYnZpZXcucG9zdE1lc3NhZ2UobXNnKTtcbiAgICB9XG4gICAgcmV0dXJuIHdpbmRvdy53ZWJraXQubWVzc2FnZUhhbmRsZXJzLmV4dGVybmFsLnBvc3RNZXNzYWdlKG1zZyk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBSZXRyaWV2ZXMgdGhlIHN5c3RlbSBkYXJrIG1vZGUgc3RhdHVzLlxuICogQHJldHVybnMge1Byb21pc2U8Ym9vbGVhbj59IC0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBib29sZWFuIHZhbHVlIGluZGljYXRpbmcgaWYgdGhlIHN5c3RlbSBpcyBpbiBkYXJrIG1vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0RhcmtNb2RlKCkge1xuICAgIHJldHVybiBjYWxsKHN5c3RlbUlzRGFya01vZGUpO1xufVxuXG4vKipcbiAqIEZldGNoZXMgdGhlIGNhcGFiaWxpdGllcyBvZiB0aGUgYXBwbGljYXRpb24gZnJvbSB0aGUgc2VydmVyLlxuICpcbiAqIEBhc3luY1xuICogQGZ1bmN0aW9uIENhcGFiaWxpdGllc1xuICogQHJldHVybnMge1Byb21pc2U8T2JqZWN0Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGNhcGFiaWxpdGllcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhcGFiaWxpdGllcygpIHtcbiAgICBsZXQgcmVzcG9uc2UgPSBmZXRjaChcIi93YWlscy9jYXBhYmlsaXRpZXNcIik7XG4gICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbn1cblxuLyoqXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBFbnZpcm9ubWVudEluZm9cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBPUyAtIFRoZSBvcGVyYXRpbmcgc3lzdGVtIGluIHVzZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBBcmNoIC0gVGhlIGFyY2hpdGVjdHVyZSBvZiB0aGUgc3lzdGVtLlxuICovXG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBSZXRyaWV2ZXMgZW52aXJvbm1lbnQgZGV0YWlscy5cbiAqIEByZXR1cm5zIHtQcm9taXNlPEVudmlyb25tZW50SW5mbz59IC0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgT1MgYW5kIHN5c3RlbSBhcmNoaXRlY3R1cmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFbnZpcm9ubWVudCgpIHtcbiAgICByZXR1cm4gY2FsbChlbnZpcm9ubWVudCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cy5cbiAqXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBvcGVyYXRpbmcgc3lzdGVtIGlzIFdpbmRvd3MsIG90aGVyd2lzZSBmYWxzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzV2luZG93cygpIHtcbiAgICByZXR1cm4gd2luZG93Ll93YWlscy5lbnZpcm9ubWVudC5PUyA9PT0gXCJ3aW5kb3dzXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgTGludXguXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIExpbnV4LCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0xpbnV4KCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcImxpbnV4XCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGlzIGEgbWFjT1Mgb3BlcmF0aW5nIHN5c3RlbS5cbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgZW52aXJvbm1lbnQgaXMgbWFjT1MsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzTWFjKCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcImRhcndpblwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQU1ENjQoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuQXJjaCA9PT0gXCJhbWQ2NFwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBhcmNoaXRlY3R1cmUgaXMgQVJNLlxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBjdXJyZW50IGFyY2hpdGVjdHVyZSBpcyBBUk0sIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQVJNKCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZS5cbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBSZXR1cm5zIHRydWUgaWYgdGhlIGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZSwgb3RoZXJ3aXNlIHJldHVybnMgZmFsc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0FSTTY0KCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtNjRcIjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIElzRGVidWcoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuRGVidWcgPT09IHRydWU7XG59XG5cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5pbXBvcnQge0lzRGVidWd9IGZyb20gXCIuL3N5c3RlbVwiO1xuXG4vLyBzZXR1cFxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgY29udGV4dE1lbnVIYW5kbGVyKTtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ29udGV4dE1lbnUsICcnKTtcbmNvbnN0IENvbnRleHRNZW51T3BlbiA9IDA7XG5cbmZ1bmN0aW9uIG9wZW5Db250ZXh0TWVudShpZCwgeCwgeSwgZGF0YSkge1xuICAgIHZvaWQgY2FsbChDb250ZXh0TWVudU9wZW4sIHtpZCwgeCwgeSwgZGF0YX0pO1xufVxuXG5mdW5jdGlvbiBjb250ZXh0TWVudUhhbmRsZXIoZXZlbnQpIHtcbiAgICAvLyBDaGVjayBmb3IgY3VzdG9tIGNvbnRleHQgbWVudVxuICAgIGxldCBlbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgIGxldCBjdXN0b21Db250ZXh0TWVudSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoXCItLWN1c3RvbS1jb250ZXh0bWVudVwiKTtcbiAgICBjdXN0b21Db250ZXh0TWVudSA9IGN1c3RvbUNvbnRleHRNZW51ID8gY3VzdG9tQ29udGV4dE1lbnUudHJpbSgpIDogXCJcIjtcbiAgICBpZiAoY3VzdG9tQ29udGV4dE1lbnUpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgbGV0IGN1c3RvbUNvbnRleHRNZW51RGF0YSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoXCItLWN1c3RvbS1jb250ZXh0bWVudS1kYXRhXCIpO1xuICAgICAgICBvcGVuQ29udGV4dE1lbnUoY3VzdG9tQ29udGV4dE1lbnUsIGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFksIGN1c3RvbUNvbnRleHRNZW51RGF0YSk7XG4gICAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpO1xufVxuXG5cbi8qXG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IGF1dG87IChkZWZhdWx0KSB3aWxsIHNob3cgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51IGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlIE9SIHRleHQgaGFzIGJlZW4gc2VsZWN0ZWQgT1IgZWxlbWVudCBpcyBpbnB1dCBvciB0ZXh0YXJlYVxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBzaG93OyB3aWxsIGFsd2F5cyBzaG93IHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBoaWRlOyB3aWxsIGFsd2F5cyBoaWRlIHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuXG5UaGlzIHJ1bGUgaXMgaW5oZXJpdGVkIGxpa2Ugbm9ybWFsIENTUyBydWxlcywgc28gbmVzdGluZyB3b3JrcyBhcyBleHBlY3RlZFxuKi9cbmZ1bmN0aW9uIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpIHtcblxuICAgIC8vIERlYnVnIGJ1aWxkcyBhbHdheXMgc2hvdyB0aGUgbWVudVxuICAgIGlmIChJc0RlYnVnKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFByb2Nlc3MgZGVmYXVsdCBjb250ZXh0IG1lbnVcbiAgICBjb25zdCBlbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgIGNvbnN0IGNvbXB1dGVkU3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KTtcbiAgICBjb25zdCBkZWZhdWx0Q29udGV4dE1lbnVBY3Rpb24gPSBjb21wdXRlZFN0eWxlLmdldFByb3BlcnR5VmFsdWUoXCItLWRlZmF1bHQtY29udGV4dG1lbnVcIikudHJpbSgpO1xuICAgIHN3aXRjaCAoZGVmYXVsdENvbnRleHRNZW51QWN0aW9uKSB7XG4gICAgICAgIGNhc2UgXCJzaG93XCI6XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNhc2UgXCJoaWRlXCI6XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgY29udGVudEVkaXRhYmxlIGlzIHRydWVcbiAgICAgICAgICAgIGlmIChlbGVtZW50LmlzQ29udGVudEVkaXRhYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0ZXh0IGhhcyBiZWVuIHNlbGVjdGVkXG4gICAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICAgICAgICBjb25zdCBoYXNTZWxlY3Rpb24gPSAoc2VsZWN0aW9uLnRvU3RyaW5nKCkubGVuZ3RoID4gMClcbiAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGVjdGlvbi5yYW5nZUNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdChpKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVjdHMgPSByYW5nZS5nZXRDbGllbnRSZWN0cygpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHJlY3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0ID0gcmVjdHNbal07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludChyZWN0LmxlZnQsIHJlY3QudG9wKSA9PT0gZWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRhZ25hbWUgaXMgaW5wdXQgb3IgdGV4dGFyZWFcbiAgICAgICAgICAgIGlmIChlbGVtZW50LnRhZ05hbWUgPT09IFwiSU5QVVRcIiB8fCBlbGVtZW50LnRhZ05hbWUgPT09IFwiVEVYVEFSRUFcIikge1xuICAgICAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24gfHwgKCFlbGVtZW50LnJlYWRPbmx5ICYmICFlbGVtZW50LmRpc2FibGVkKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBoaWRlIGRlZmF1bHQgY29udGV4dCBtZW51XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIFJldHJpZXZlcyB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBzcGVjaWZpZWQga2V5IGZyb20gdGhlIGZsYWcgbWFwLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXlTdHJpbmcgLSBUaGUga2V5IHRvIHJldHJpZXZlIHRoZSB2YWx1ZSBmb3IuXG4gKiBAcmV0dXJuIHsqfSAtIFRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBrZXkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRGbGFnKGtleVN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmZsYWdzW2tleVN0cmluZ107XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gcmV0cmlldmUgZmxhZyAnXCIgKyBrZXlTdHJpbmcgKyBcIic6IFwiICsgZSk7XG4gICAgfVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7aW52b2tlLCBJc1dpbmRvd3N9IGZyb20gXCIuL3N5c3RlbVwiO1xuaW1wb3J0IHtHZXRGbGFnfSBmcm9tIFwiLi9mbGFnc1wiO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLnNldFJlc2l6YWJsZSA9IHNldFJlc2l6YWJsZTtcbndpbmRvdy5fd2FpbHMuZW5kRHJhZyA9IGVuZERyYWc7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgb25Nb3VzZURvd24pO1xud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG9uTW91c2VNb3ZlKTtcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25Nb3VzZVVwKTtcblxuXG5sZXQgc2hvdWxkRHJhZyA9IGZhbHNlO1xubGV0IHJlc2l6ZUVkZ2UgPSBudWxsO1xubGV0IHJlc2l6YWJsZSA9IGZhbHNlO1xubGV0IGRlZmF1bHRDdXJzb3IgPSBcImF1dG9cIjtcblxuZnVuY3Rpb24gZHJhZ1Rlc3QoZSkge1xuICAgIGxldCB2YWwgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlLnRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZShcIi0td2Via2l0LWFwcC1yZWdpb25cIik7XG4gICAgaWYgKCF2YWwgfHwgdmFsID09PSBcIlwiIHx8IHZhbC50cmltKCkgIT09IFwiZHJhZ1wiIHx8IGUuYnV0dG9ucyAhPT0gMSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBlLmRldGFpbCA9PT0gMTtcbn1cblxuZnVuY3Rpb24gc2V0UmVzaXphYmxlKHZhbHVlKSB7XG4gICAgcmVzaXphYmxlID0gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIGVuZERyYWcoKSB7XG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5jdXJzb3IgPSAnZGVmYXVsdCc7XG4gICAgc2hvdWxkRHJhZyA9IGZhbHNlO1xufVxuXG5mdW5jdGlvbiB0ZXN0UmVzaXplKCkge1xuICAgIGlmKCByZXNpemVFZGdlICkge1xuICAgICAgICBpbnZva2UoYHJlc2l6ZToke3Jlc2l6ZUVkZ2V9YCk7XG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gb25Nb3VzZURvd24oZSkge1xuICAgIGlmKElzV2luZG93cygpICYmIHRlc3RSZXNpemUoKSB8fCBkcmFnVGVzdChlKSkge1xuICAgICAgICBzaG91bGREcmFnID0gISFpc1ZhbGlkRHJhZyhlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzVmFsaWREcmFnKGUpIHtcbiAgICAvLyBJZ25vcmUgZHJhZyBvbiBzY3JvbGxiYXJzXG4gICAgcmV0dXJuICEoZS5vZmZzZXRYID4gZS50YXJnZXQuY2xpZW50V2lkdGggfHwgZS5vZmZzZXRZID4gZS50YXJnZXQuY2xpZW50SGVpZ2h0KTtcbn1cblxuZnVuY3Rpb24gb25Nb3VzZVVwKGUpIHtcbiAgICBsZXQgbW91c2VQcmVzc2VkID0gZS5idXR0b25zICE9PSB1bmRlZmluZWQgPyBlLmJ1dHRvbnMgOiBlLndoaWNoO1xuICAgIGlmIChtb3VzZVByZXNzZWQgPiAwKSB7XG4gICAgICAgIGVuZERyYWcoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldFJlc2l6ZShjdXJzb3IgPSBkZWZhdWx0Q3Vyc29yKSB7XG4gICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmN1cnNvciA9IGN1cnNvcjtcbiAgICByZXNpemVFZGdlID0gY3Vyc29yO1xufVxuXG5mdW5jdGlvbiBvbk1vdXNlTW92ZShlKSB7XG4gICAgc2hvdWxkRHJhZyA9IGNoZWNrRHJhZyhlKTtcbiAgICBpZiAoSXNXaW5kb3dzKCkgJiYgcmVzaXphYmxlKSB7XG4gICAgICAgIGhhbmRsZVJlc2l6ZShlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrRHJhZyhlKSB7XG4gICAgbGV0IG1vdXNlUHJlc3NlZCA9IGUuYnV0dG9ucyAhPT0gdW5kZWZpbmVkID8gZS5idXR0b25zIDogZS53aGljaDtcbiAgICBpZihzaG91bGREcmFnICYmIG1vdXNlUHJlc3NlZCA+IDApIHtcbiAgICAgICAgaW52b2tlKFwiZHJhZ1wiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gc2hvdWxkRHJhZztcbn1cblxuZnVuY3Rpb24gaGFuZGxlUmVzaXplKGUpIHtcbiAgICBsZXQgcmVzaXplSGFuZGxlSGVpZ2h0ID0gR2V0RmxhZyhcInN5c3RlbS5yZXNpemVIYW5kbGVIZWlnaHRcIikgfHwgNTtcbiAgICBsZXQgcmVzaXplSGFuZGxlV2lkdGggPSBHZXRGbGFnKFwic3lzdGVtLnJlc2l6ZUhhbmRsZVdpZHRoXCIpIHx8IDU7XG5cbiAgICAvLyBFeHRyYSBwaXhlbHMgZm9yIHRoZSBjb3JuZXIgYXJlYXNcbiAgICBsZXQgY29ybmVyRXh0cmEgPSBHZXRGbGFnKFwicmVzaXplQ29ybmVyRXh0cmFcIikgfHwgMTA7XG5cbiAgICBsZXQgcmlnaHRCb3JkZXIgPSB3aW5kb3cub3V0ZXJXaWR0aCAtIGUuY2xpZW50WCA8IHJlc2l6ZUhhbmRsZVdpZHRoO1xuICAgIGxldCBsZWZ0Qm9yZGVyID0gZS5jbGllbnRYIDwgcmVzaXplSGFuZGxlV2lkdGg7XG4gICAgbGV0IHRvcEJvcmRlciA9IGUuY2xpZW50WSA8IHJlc2l6ZUhhbmRsZUhlaWdodDtcbiAgICBsZXQgYm90dG9tQm9yZGVyID0gd2luZG93Lm91dGVySGVpZ2h0IC0gZS5jbGllbnRZIDwgcmVzaXplSGFuZGxlSGVpZ2h0O1xuXG4gICAgLy8gQWRqdXN0IGZvciBjb3JuZXJzXG4gICAgbGV0IHJpZ2h0Q29ybmVyID0gd2luZG93Lm91dGVyV2lkdGggLSBlLmNsaWVudFggPCAocmVzaXplSGFuZGxlV2lkdGggKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IGxlZnRDb3JuZXIgPSBlLmNsaWVudFggPCAocmVzaXplSGFuZGxlV2lkdGggKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IHRvcENvcm5lciA9IGUuY2xpZW50WSA8IChyZXNpemVIYW5kbGVIZWlnaHQgKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IGJvdHRvbUNvcm5lciA9IHdpbmRvdy5vdXRlckhlaWdodCAtIGUuY2xpZW50WSA8IChyZXNpemVIYW5kbGVIZWlnaHQgKyBjb3JuZXJFeHRyYSk7XG5cbiAgICAvLyBJZiB3ZSBhcmVuJ3Qgb24gYW4gZWRnZSwgYnV0IHdlcmUsIHJlc2V0IHRoZSBjdXJzb3IgdG8gZGVmYXVsdFxuICAgIGlmICghbGVmdEJvcmRlciAmJiAhcmlnaHRCb3JkZXIgJiYgIXRvcEJvcmRlciAmJiAhYm90dG9tQm9yZGVyICYmIHJlc2l6ZUVkZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzZXRSZXNpemUoKTtcbiAgICB9XG4gICAgLy8gQWRqdXN0ZWQgZm9yIGNvcm5lciBhcmVhc1xuICAgIGVsc2UgaWYgKHJpZ2h0Q29ybmVyICYmIGJvdHRvbUNvcm5lcikgc2V0UmVzaXplKFwic2UtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRDb3JuZXIgJiYgYm90dG9tQ29ybmVyKSBzZXRSZXNpemUoXCJzdy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAobGVmdENvcm5lciAmJiB0b3BDb3JuZXIpIHNldFJlc2l6ZShcIm53LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BDb3JuZXIgJiYgcmlnaHRDb3JuZXIpIHNldFJlc2l6ZShcIm5lLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Qm9yZGVyKSBzZXRSZXNpemUoXCJ3LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BCb3JkZXIpIHNldFJlc2l6ZShcIm4tcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwicy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAocmlnaHRCb3JkZXIpIHNldFJlc2l6ZShcImUtcmVzaXplXCIpO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUG9zaXRpb25cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIFggY29vcmRpbmF0ZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBZIC0gVGhlIFkgY29vcmRpbmF0ZS5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNpemVcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIHdpZHRoLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFkgLSBUaGUgaGVpZ2h0LlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBSZWN0XG4gKiBAcHJvcGVydHkge251bWJlcn0gWCAtIFRoZSBYIGNvb3JkaW5hdGUgb2YgdGhlIHRvcC1sZWZ0IGNvcm5lci5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBZIC0gVGhlIFkgY29vcmRpbmF0ZSBvZiB0aGUgdG9wLWxlZnQgY29ybmVyLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSByZWN0YW5nbGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gSGVpZ2h0IC0gVGhlIGhlaWdodCBvZiB0aGUgcmVjdGFuZ2xlLlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7KCdaZXJvJ3wnTmluZXR5J3wnT25lRWlnaHR5J3wnVHdvU2V2ZW50eScpfSBSb3RhdGlvblxuICogVGhlIHJvdGF0aW9uIG9mIHRoZSBzY3JlZW4uIENhbiBiZSBvbmUgb2YgJ1plcm8nLCAnTmluZXR5JywgJ09uZUVpZ2h0eScsICdUd29TZXZlbnR5Jy5cbiAqL1xuXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gU2NyZWVuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSWQgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHNjcmVlbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBOYW1lIC0gSHVtYW4gcmVhZGFibGUgbmFtZSBvZiB0aGUgc2NyZWVuLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFNjYWxlIC0gVGhlIHJlc29sdXRpb24gc2NhbGUgb2YgdGhlIHNjcmVlbi4gMSA9IHN0YW5kYXJkIHJlc29sdXRpb24sIDIgPSBoaWdoIChSZXRpbmEpLCBldGMuXG4gKiBAcHJvcGVydHkge1Bvc2l0aW9ufSBQb3NpdGlvbiAtIENvbnRhaW5zIHRoZSBYIGFuZCBZIGNvb3JkaW5hdGVzIG9mIHRoZSBzY3JlZW4ncyBwb3NpdGlvbi5cbiAqIEBwcm9wZXJ0eSB7U2l6ZX0gU2l6ZSAtIENvbnRhaW5zIHRoZSB3aWR0aCBhbmQgaGVpZ2h0IG9mIHRoZSBzY3JlZW4uXG4gKiBAcHJvcGVydHkge1JlY3R9IEJvdW5kcyAtIENvbnRhaW5zIHRoZSBib3VuZHMgb2YgdGhlIHNjcmVlbiBpbiB0ZXJtcyBvZiBYLCBZLCBXaWR0aCwgYW5kIEhlaWdodC5cbiAqIEBwcm9wZXJ0eSB7UmVjdH0gV29ya0FyZWEgLSBDb250YWlucyB0aGUgYXJlYSBvZiB0aGUgc2NyZWVuIHRoYXQgaXMgYWN0dWFsbHkgdXNhYmxlIChleGNsdWRpbmcgdGFza2JhciBhbmQgb3RoZXIgc3lzdGVtIFVJKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gSXNQcmltYXJ5IC0gVHJ1ZSBpZiB0aGlzIGlzIHRoZSBwcmltYXJ5IG1vbml0b3Igc2VsZWN0ZWQgYnkgdGhlIHVzZXIgaW4gdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gKiBAcHJvcGVydHkge1JvdGF0aW9ufSBSb3RhdGlvbiAtIFRoZSByb3RhdGlvbiBvZiB0aGUgc2NyZWVuLlxuICovXG5cblxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU2NyZWVucywgJycpO1xuXG5jb25zdCBnZXRBbGwgPSAwO1xuY29uc3QgZ2V0UHJpbWFyeSA9IDE7XG5jb25zdCBnZXRDdXJyZW50ID0gMjtcblxuLyoqXG4gKiBHZXRzIGFsbCBzY3JlZW5zLlxuICogQHJldHVybnMge1Byb21pc2U8U2NyZWVuW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiBTY3JlZW4gb2JqZWN0cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldEFsbCgpIHtcbiAgICByZXR1cm4gY2FsbChnZXRBbGwpO1xufVxuLyoqXG4gKiBHZXRzIHRoZSBwcmltYXJ5IHNjcmVlbi5cbiAqIEByZXR1cm5zIHtQcm9taXNlPFNjcmVlbj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBwcmltYXJ5IHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldFByaW1hcnkoKSB7XG4gICAgcmV0dXJuIGNhbGwoZ2V0UHJpbWFyeSk7XG59XG4vKipcbiAqIEdldHMgdGhlIGN1cnJlbnQgYWN0aXZlIHNjcmVlbi5cbiAqXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxTY3JlZW4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjdXJyZW50IGFjdGl2ZSBzY3JlZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRDdXJyZW50KCkge1xuICAgIHJldHVybiBjYWxsKGdldEN1cnJlbnQpO1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vLyBJbXBvcnQgc2NyZWVuIGpzZG9jIGRlZmluaXRpb24gZnJvbSAuL3NjcmVlbnMuanNcbi8qKlxuICogQHR5cGVkZWYge2ltcG9ydChcIi4vc2NyZWVuc1wiKS5TY3JlZW59IFNjcmVlblxuICovXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcblxuY29uc3QgY2VudGVyID0gMDtcbmNvbnN0IHNldFRpdGxlID0gMTtcbmNvbnN0IGZ1bGxzY3JlZW4gPSAyO1xuY29uc3QgdW5GdWxsc2NyZWVuID0gMztcbmNvbnN0IHNldFNpemUgPSA0O1xuY29uc3Qgc2l6ZSA9IDU7XG5jb25zdCBzZXRNYXhTaXplID0gNjtcbmNvbnN0IHNldE1pblNpemUgPSA3O1xuY29uc3Qgc2V0QWx3YXlzT25Ub3AgPSA4O1xuY29uc3Qgc2V0UmVsYXRpdmVQb3NpdGlvbiA9IDk7XG5jb25zdCByZWxhdGl2ZVBvc2l0aW9uID0gMTA7XG5jb25zdCBzY3JlZW4gPSAxMTtcbmNvbnN0IGhpZGUgPSAxMjtcbmNvbnN0IG1heGltaXNlID0gMTM7XG5jb25zdCB1bk1heGltaXNlID0gMTQ7XG5jb25zdCB0b2dnbGVNYXhpbWlzZSA9IDE1O1xuY29uc3QgbWluaW1pc2UgPSAxNjtcbmNvbnN0IHVuTWluaW1pc2UgPSAxNztcbmNvbnN0IHJlc3RvcmUgPSAxODtcbmNvbnN0IHNob3cgPSAxOTtcbmNvbnN0IGNsb3NlID0gMjA7XG5jb25zdCBzZXRCYWNrZ3JvdW5kQ29sb3VyID0gMjE7XG5jb25zdCBzZXRSZXNpemFibGUgPSAyMjtcbmNvbnN0IHdpZHRoID0gMjM7XG5jb25zdCBoZWlnaHQgPSAyNDtcbmNvbnN0IHpvb21JbiA9IDI1O1xuY29uc3Qgem9vbU91dCA9IDI2O1xuY29uc3Qgem9vbVJlc2V0ID0gMjc7XG5jb25zdCBnZXRab29tTGV2ZWwgPSAyODtcbmNvbnN0IHNldFpvb21MZXZlbCA9IDI5O1xuXG5jb25zdCB0aGlzV2luZG93ID0gR2V0KCcnKTtcblxuZnVuY3Rpb24gY3JlYXRlV2luZG93KGNhbGwpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBHZXQ6ICh3aW5kb3dOYW1lKSA9PiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKSxcbiAgICAgICAgQ2VudGVyOiAoKSA9PiBjYWxsKGNlbnRlciksXG4gICAgICAgIFNldFRpdGxlOiAodGl0bGUpID0+IGNhbGwoc2V0VGl0bGUsIHt0aXRsZX0pLFxuICAgICAgICBGdWxsc2NyZWVuOiAoKSA9PiBjYWxsKGZ1bGxzY3JlZW4pLFxuICAgICAgICBVbkZ1bGxzY3JlZW46ICgpID0+IGNhbGwodW5GdWxsc2NyZWVuKSxcbiAgICAgICAgU2V0U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2l6ZTogKCkgPT4gY2FsbChzaXplKSxcbiAgICAgICAgU2V0TWF4U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWF4U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2V0TWluU2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWluU2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2V0QWx3YXlzT25Ub3A6IChvblRvcCkgPT4gY2FsbChzZXRBbHdheXNPblRvcCwge2Fsd2F5c09uVG9wOiBvblRvcH0pLFxuICAgICAgICBTZXRSZWxhdGl2ZVBvc2l0aW9uOiAoeCwgeSkgPT4gY2FsbChzZXRSZWxhdGl2ZVBvc2l0aW9uLCB7eCwgeX0pLFxuICAgICAgICBSZWxhdGl2ZVBvc2l0aW9uOiAoKSA9PiBjYWxsKHJlbGF0aXZlUG9zaXRpb24pLFxuICAgICAgICBTY3JlZW46ICgpID0+IGNhbGwoc2NyZWVuKSxcbiAgICAgICAgSGlkZTogKCkgPT4gY2FsbChoaWRlKSxcbiAgICAgICAgTWF4aW1pc2U6ICgpID0+IGNhbGwobWF4aW1pc2UpLFxuICAgICAgICBVbk1heGltaXNlOiAoKSA9PiBjYWxsKHVuTWF4aW1pc2UpLFxuICAgICAgICBUb2dnbGVNYXhpbWlzZTogKCkgPT4gY2FsbCh0b2dnbGVNYXhpbWlzZSksXG4gICAgICAgIE1pbmltaXNlOiAoKSA9PiBjYWxsKG1pbmltaXNlKSxcbiAgICAgICAgVW5NaW5pbWlzZTogKCkgPT4gY2FsbCh1bk1pbmltaXNlKSxcbiAgICAgICAgUmVzdG9yZTogKCkgPT4gY2FsbChyZXN0b3JlKSxcbiAgICAgICAgU2hvdzogKCkgPT4gY2FsbChzaG93KSxcbiAgICAgICAgQ2xvc2U6ICgpID0+IGNhbGwoY2xvc2UpLFxuICAgICAgICBTZXRCYWNrZ3JvdW5kQ29sb3VyOiAociwgZywgYiwgYSkgPT4gY2FsbChzZXRCYWNrZ3JvdW5kQ29sb3VyLCB7ciwgZywgYiwgYX0pLFxuICAgICAgICBTZXRSZXNpemFibGU6IChyZXNpemFibGUpID0+IGNhbGwoc2V0UmVzaXphYmxlLCB7cmVzaXphYmxlfSksXG4gICAgICAgIFdpZHRoOiAoKSA9PiBjYWxsKHdpZHRoKSxcbiAgICAgICAgSGVpZ2h0OiAoKSA9PiBjYWxsKGhlaWdodCksXG4gICAgICAgIFpvb21JbjogKCkgPT4gY2FsbCh6b29tSW4pLFxuICAgICAgICBab29tT3V0OiAoKSA9PiBjYWxsKHpvb21PdXQpLFxuICAgICAgICBab29tUmVzZXQ6ICgpID0+IGNhbGwoem9vbVJlc2V0KSxcbiAgICAgICAgR2V0Wm9vbUxldmVsOiAoKSA9PiBjYWxsKGdldFpvb21MZXZlbCksXG4gICAgICAgIFNldFpvb21MZXZlbDogKHpvb21MZXZlbCkgPT4gY2FsbChzZXRab29tTGV2ZWwsIHt6b29tTGV2ZWx9KSxcbiAgICB9O1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNwZWNpZmllZCB3aW5kb3cuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHdpbmRvd05hbWUgLSBUaGUgbmFtZSBvZiB0aGUgd2luZG93IHRvIGdldC5cbiAqIEByZXR1cm4ge09iamVjdH0gLSBUaGUgc3BlY2lmaWVkIHdpbmRvdyBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXQod2luZG93TmFtZSkge1xuICAgIHJldHVybiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKTtcbn1cblxuLyoqXG4gKiBDZW50ZXJzIHRoZSB3aW5kb3cgb24gdGhlIHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENlbnRlcigpIHtcbiAgICB0aGlzV2luZG93LkNlbnRlcigpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIHRpdGxlIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGUgLSBUaGUgdGl0bGUgdG8gc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0VGl0bGUodGl0bGUpIHtcbiAgICB0aGlzV2luZG93LlNldFRpdGxlKHRpdGxlKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSB3aW5kb3cgdG8gZnVsbHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEZ1bGxzY3JlZW4oKSB7XG4gICAgdGhpc1dpbmRvdy5GdWxsc2NyZWVuKCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgc2l6ZSBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdGhpc1dpbmRvdy5TZXRTaXplKHdpZHRoLCBoZWlnaHQpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNpemUoKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2l6ZSgpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIG1heGltdW0gd2lkdGggb2YgdGhlIHdpbmRvdy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgLSBUaGUgbWF4aW11bSBoZWlnaHQgb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldE1heFNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXNXaW5kb3cuU2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aCAtIFRoZSBtaW5pbXVtIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIG1pbmltdW0gaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzV2luZG93LlNldE1pblNpemUod2lkdGgsIGhlaWdodCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgd2luZG93IHRvIGFsd2F5cyBiZSBvbiB0b3AuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IG9uVG9wIC0gV2hldGhlciB0aGUgd2luZG93IHNob3VsZCBhbHdheXMgYmUgb24gdG9wLlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0QWx3YXlzT25Ub3Aob25Ub3ApIHtcbiAgICB0aGlzV2luZG93LlNldEFsd2F5c09uVG9wKG9uVG9wKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSByZWxhdGl2ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHggLSBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSB3aW5kb3cncyBwb3NpdGlvbi5cbiAqIEBwYXJhbSB7bnVtYmVyfSB5IC0gVGhlIHktY29vcmRpbmF0ZSBvZiB0aGUgd2luZG93J3MgcG9zaXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRSZWxhdGl2ZVBvc2l0aW9uKHgsIHkpIHtcbiAgICB0aGlzV2luZG93LlNldFJlbGF0aXZlUG9zaXRpb24oeCwgeSk7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFJlbGF0aXZlUG9zaXRpb24oKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuUmVsYXRpdmVQb3NpdGlvbigpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNjcmVlbiB0aGF0IHRoZSB3aW5kb3cgaXMgb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTY3JlZW4oKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2NyZWVuKCk7XG59XG5cbi8qKlxuICogSGlkZXMgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XG4gICAgdGhpc1dpbmRvdy5IaWRlKCk7XG59XG5cbi8qKlxuICogTWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBNYXhpbWlzZSgpIHtcbiAgICB0aGlzV2luZG93Lk1heGltaXNlKCk7XG59XG5cbi8qKlxuICogVW4tbWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBVbk1heGltaXNlKCkge1xuICAgIHRoaXNXaW5kb3cuVW5NYXhpbWlzZSgpO1xufVxuXG4vKipcbiAqIFRvZ2dsZXMgdGhlIG1heGltaXNhdGlvbiBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gVG9nZ2xlTWF4aW1pc2UoKSB7XG4gICAgdGhpc1dpbmRvdy5Ub2dnbGVNYXhpbWlzZSgpO1xufVxuXG4vKipcbiAqIE1pbmltaXNlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gTWluaW1pc2UoKSB7XG4gICAgdGhpc1dpbmRvdy5NaW5pbWlzZSgpO1xufVxuXG4vKipcbiAqIFVuLW1pbmltaXNlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gVW5NaW5pbWlzZSgpIHtcbiAgICB0aGlzV2luZG93LlVuTWluaW1pc2UoKTtcbn1cblxuLyoqXG4gKiBSZXN0b3JlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVzdG9yZSgpIHtcbiAgICB0aGlzV2luZG93LlJlc3RvcmUoKTtcbn1cblxuLyoqXG4gKiBTaG93cyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpIHtcbiAgICB0aGlzV2luZG93LlNob3coKTtcbn1cblxuLyoqXG4gKiBDbG9zZXMgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENsb3NlKCkge1xuICAgIHRoaXNXaW5kb3cuQ2xvc2UoKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBiYWNrZ3JvdW5kIGNvbG91ciBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHIgLSBUaGUgcmVkIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxuICogQHBhcmFtIHtudW1iZXJ9IGcgLSBUaGUgZ3JlZW4gY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXG4gKiBAcGFyYW0ge251bWJlcn0gYiAtIFRoZSBibHVlIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxuICogQHBhcmFtIHtudW1iZXJ9IGEgLSBUaGUgYWxwaGEgY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRCYWNrZ3JvdW5kQ29sb3VyKHIsIGcsIGIsIGEpIHtcbiAgICB0aGlzV2luZG93LlNldEJhY2tncm91bmRDb2xvdXIociwgZywgYiwgYSk7XG59XG5cbi8qKlxuICogU2V0cyB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgcmVzaXphYmxlLlxuICogQHBhcmFtIHtib29sZWFufSByZXNpemFibGUgLSBXaGV0aGVyIHRoZSB3aW5kb3cgc2hvdWxkIGJlIHJlc2l6YWJsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldFJlc2l6YWJsZShyZXNpemFibGUpIHtcbiAgICB0aGlzV2luZG93LlNldFJlc2l6YWJsZShyZXNpemFibGUpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaWR0aCgpIHtcbiAgICByZXR1cm4gdGhpc1dpbmRvdy5XaWR0aCgpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gSGVpZ2h0KCkge1xuICAgIHJldHVybiB0aGlzV2luZG93LkhlaWdodCgpO1xufVxuXG4vKipcbiAqIFpvb21zIGluIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBab29tSW4oKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tSW4oKTtcbn1cblxuLyoqXG4gKiBab29tcyBvdXQgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFpvb21PdXQoKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tT3V0KCk7XG59XG5cbi8qKlxuICogUmVzZXRzIHRoZSB6b29tIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBab29tUmVzZXQoKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tUmVzZXQoKTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRab29tTGV2ZWwoKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuR2V0Wm9vbUxldmVsKCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHpvb21MZXZlbCAtIFRoZSB6b29tIGxldmVsIHRvIHNldC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldFpvb21MZXZlbCh6b29tTGV2ZWwpIHtcbiAgICB0aGlzV2luZG93LlNldFpvb21MZXZlbCh6b29tTGV2ZWwpO1xufVxuIiwgIlxuaW1wb3J0IHtFbWl0LCBXYWlsc0V2ZW50fSBmcm9tIFwiLi9ldmVudHNcIjtcbmltcG9ydCB7UXVlc3Rpb259IGZyb20gXCIuL2RpYWxvZ3NcIjtcbmltcG9ydCB7R2V0fSBmcm9tIFwiLi93aW5kb3dcIjtcbmltcG9ydCB7T3BlblVSTH0gZnJvbSBcIi4vYnJvd3NlclwiO1xuXG4vKipcbiAqIFNlbmRzIGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIG9wdGlvbmFsIGRhdGEuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBzZW5kLlxuICogQHBhcmFtIHthbnl9IFtkYXRhPW51bGxdIC0gT3B0aW9uYWwgZGF0YSB0byBzZW5kIGFsb25nIHdpdGggdGhlIGV2ZW50LlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHNlbmRFdmVudChldmVudE5hbWUsIGRhdGE9bnVsbCkge1xuICAgIGxldCBldmVudCA9IG5ldyBXYWlsc0V2ZW50KGV2ZW50TmFtZSwgZGF0YSk7XG4gICAgRW1pdChldmVudCk7XG59XG5cbi8qKlxuICogQWRkcyBldmVudCBsaXN0ZW5lcnMgdG8gZWxlbWVudHMgd2l0aCBgd21sLWV2ZW50YCBhdHRyaWJ1dGUuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gYWRkV01MRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLWV2ZW50XScpO1xuICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZXZlbnRUeXBlID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1ldmVudCcpO1xuICAgICAgICBjb25zdCBjb25maXJtID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1jb25maXJtJyk7XG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XG5cbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIERldGFjaGVkOiBmYWxzZSwgQnV0dG9uczpbe0xhYmVsOlwiWWVzXCJ9LHtMYWJlbDpcIk5vXCIsIElzRGVmYXVsdDp0cnVlfV19KS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPT0gXCJOb1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kRXZlbnQoZXZlbnRUeXBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbmRFdmVudChldmVudFR5cGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFJlbW92ZSBleGlzdGluZyBsaXN0ZW5lcnNcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcblxuICAgICAgICAvLyBBZGQgbmV3IGxpc3RlbmVyXG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XG4gICAgfSk7XG59XG5cblxuLyoqXG4gKiBDYWxscyBhIG1ldGhvZCBvbiBhIHNwZWNpZmllZCB3aW5kb3cuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgdG8gY2FsbCB0aGUgbWV0aG9kIG9uLlxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZCAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqL1xuZnVuY3Rpb24gY2FsbFdpbmRvd01ldGhvZCh3aW5kb3dOYW1lLCBtZXRob2QpIHtcbiAgICBsZXQgdGFyZ2V0V2luZG93ID0gR2V0KHdpbmRvd05hbWUpO1xuICAgIGxldCBtZXRob2RNYXAgPSBXaW5kb3dNZXRob2RzKHRhcmdldFdpbmRvdyk7XG4gICAgaWYgKCFtZXRob2RNYXAuaGFzKG1ldGhvZCkpIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJXaW5kb3cgbWV0aG9kIFwiICsgbWV0aG9kICsgXCIgbm90IGZvdW5kXCIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBtZXRob2RNYXAuZ2V0KG1ldGhvZCkoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBjYWxsaW5nIHdpbmRvdyBtZXRob2QgJ1wiICsgbWV0aG9kICsgXCInOiBcIiArIGUpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBZGRzIHdpbmRvdyBsaXN0ZW5lcnMgZm9yIGVsZW1lbnRzIHdpdGggdGhlICd3bWwtd2luZG93JyBhdHRyaWJ1dGUuXG4gKiBSZW1vdmVzIGFueSBleGlzdGluZyBsaXN0ZW5lcnMgYmVmb3JlIGFkZGluZyBuZXcgb25lcy5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5mdW5jdGlvbiBhZGRXTUxXaW5kb3dMaXN0ZW5lcnMoKSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLXdpbmRvd10nKTtcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IHdpbmRvd01ldGhvZCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtd2luZG93Jyk7XG4gICAgICAgIGNvbnN0IGNvbmZpcm0gPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWNvbmZpcm0nKTtcbiAgICAgICAgY29uc3QgdHJpZ2dlciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdHJpZ2dlcicpIHx8ICdjbGljayc7XG4gICAgICAgIGNvbnN0IHRhcmdldFdpbmRvdyA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdGFyZ2V0LXdpbmRvdycpIHx8ICcnO1xuXG4gICAgICAgIGxldCBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjb25maXJtKSB7XG4gICAgICAgICAgICAgICAgUXVlc3Rpb24oe1RpdGxlOiBcIkNvbmZpcm1cIiwgTWVzc2FnZTpjb25maXJtLCBCdXR0b25zOlt7TGFiZWw6XCJZZXNcIn0se0xhYmVsOlwiTm9cIiwgSXNEZWZhdWx0OnRydWV9XX0pLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9PSBcIk5vXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxXaW5kb3dNZXRob2QodGFyZ2V0V2luZG93LCB3aW5kb3dNZXRob2QpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FsbFdpbmRvd01ldGhvZCh0YXJnZXRXaW5kb3csIHdpbmRvd01ldGhvZCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUmVtb3ZlIGV4aXN0aW5nIGxpc3RlbmVyc1xuICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xuXG4gICAgICAgIC8vIEFkZCBuZXcgbGlzdGVuZXJcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBBZGRzIGEgbGlzdGVuZXIgdG8gZWxlbWVudHMgd2l0aCB0aGUgJ3dtbC1vcGVudXJsJyBhdHRyaWJ1dGUuXG4gKiBXaGVuIHRoZSBzcGVjaWZpZWQgdHJpZ2dlciBldmVudCBpcyBmaXJlZCBvbiBhbnkgb2YgdGhlc2UgZWxlbWVudHMsXG4gKiB0aGUgbGlzdGVuZXIgd2lsbCBvcGVuIHRoZSBVUkwgc3BlY2lmaWVkIGJ5IHRoZSAnd21sLW9wZW51cmwnIGF0dHJpYnV0ZS5cbiAqIElmIGEgJ3dtbC1jb25maXJtJyBhdHRyaWJ1dGUgaXMgcHJvdmlkZWQsIGEgY29uZmlybWF0aW9uIGRpYWxvZyB3aWxsIGJlIGRpc3BsYXllZCxcbiAqIGFuZCB0aGUgVVJMIHdpbGwgb25seSBiZSBvcGVuZWQgaWYgdGhlIHVzZXIgY29uZmlybXMuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpIHtcbiAgICBjb25zdCBlbGVtZW50cyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ1t3bWwtb3BlbnVybF0nKTtcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IHVybCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtb3BlbnVybCcpO1xuICAgICAgICBjb25zdCBjb25maXJtID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1jb25maXJtJyk7XG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XG5cbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIEJ1dHRvbnM6W3tMYWJlbDpcIlllc1wifSx7TGFiZWw6XCJOb1wiLCBJc0RlZmF1bHQ6dHJ1ZX1dfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT09IFwiTm9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCBPcGVuVVJMKHVybCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2b2lkIE9wZW5VUkwodXJsKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZW1vdmUgZXhpc3RpbmcgbGlzdGVuZXJzXG4gICAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XG5cbiAgICAgICAgLy8gQWRkIG5ldyBsaXN0ZW5lclxuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIFJlbG9hZHMgdGhlIFdNTCBwYWdlIGJ5IGFkZGluZyBuZWNlc3NhcnkgZXZlbnQgbGlzdGVuZXJzIGFuZCBicm93c2VyIGxpc3RlbmVycy5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVsb2FkKCkge1xuICAgIGFkZFdNTEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgYWRkV01MV2luZG93TGlzdGVuZXJzKCk7XG4gICAgYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBtYXAgb2YgYWxsIG1ldGhvZHMgaW4gdGhlIGN1cnJlbnQgd2luZG93LlxuICogQHJldHVybnMge01hcH0gLSBBIG1hcCBvZiB3aW5kb3cgbWV0aG9kcy5cbiAqL1xuZnVuY3Rpb24gV2luZG93TWV0aG9kcyh0YXJnZXRXaW5kb3cpIHtcbiAgICAvLyBDcmVhdGUgYSBuZXcgbWFwIHRvIHN0b3JlIG1ldGhvZHNcbiAgICBsZXQgcmVzdWx0ID0gbmV3IE1hcCgpO1xuXG4gICAgLy8gSXRlcmF0ZSBvdmVyIGFsbCBwcm9wZXJ0aWVzIG9mIHRoZSB3aW5kb3cgb2JqZWN0XG4gICAgZm9yIChsZXQgbWV0aG9kIGluIHRhcmdldFdpbmRvdykge1xuICAgICAgICAvLyBDaGVjayBpZiB0aGUgcHJvcGVydHkgaXMgaW5kZWVkIGEgbWV0aG9kIChmdW5jdGlvbilcbiAgICAgICAgaWYodHlwZW9mIHRhcmdldFdpbmRvd1ttZXRob2RdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAvLyBBZGQgdGhlIG1ldGhvZCB0byB0aGUgbWFwXG4gICAgICAgICAgICByZXN1bHQuc2V0KG1ldGhvZCwgdGFyZ2V0V2luZG93W21ldGhvZF0pO1xuICAgICAgICB9XG5cbiAgICB9XG4gICAgLy8gUmV0dXJuIHRoZSBtYXAgb2Ygd2luZG93IG1ldGhvZHNcbiAgICByZXR1cm4gcmVzdWx0O1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtpbXBvcnQoXCIuL3R5cGVzXCIpLldhaWxzRXZlbnR9IFdhaWxzRXZlbnRcbiAqL1xuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuXG5pbXBvcnQge0V2ZW50VHlwZXN9IGZyb20gXCIuL2V2ZW50X3R5cGVzXCI7XG5leHBvcnQgY29uc3QgVHlwZXMgPSBFdmVudFR5cGVzO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLmRpc3BhdGNoV2FpbHNFdmVudCA9IGRpc3BhdGNoV2FpbHNFdmVudDtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuRXZlbnRzLCAnJyk7XG5jb25zdCBFbWl0TWV0aG9kID0gMDtcbmNvbnN0IGV2ZW50TGlzdGVuZXJzID0gbmV3IE1hcCgpO1xuXG5jbGFzcyBMaXN0ZW5lciB7XG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgICAgIHRoaXMuZXZlbnROYW1lID0gZXZlbnROYW1lO1xuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICAgICAgdGhpcy5DYWxsYmFjayA9IChkYXRhKSA9PiB7XG4gICAgICAgICAgICBjYWxsYmFjayhkYXRhKTtcbiAgICAgICAgICAgIGlmICh0aGlzLm1heENhbGxiYWNrcyA9PT0gLTEpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMubWF4Q2FsbGJhY2tzIC09IDE7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXhDYWxsYmFja3MgPT09IDA7XG4gICAgICAgIH07XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2FpbHNFdmVudCB7XG4gICAgY29uc3RydWN0b3IobmFtZSwgZGF0YSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cCgpIHtcbn1cblxuZnVuY3Rpb24gZGlzcGF0Y2hXYWlsc0V2ZW50KGV2ZW50KSB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudC5uYW1lKTtcbiAgICBpZiAobGlzdGVuZXJzKSB7XG4gICAgICAgIGxldCB0b1JlbW92ZSA9IGxpc3RlbmVycy5maWx0ZXIobGlzdGVuZXIgPT4ge1xuICAgICAgICAgICAgbGV0IHJlbW92ZSA9IGxpc3RlbmVyLkNhbGxiYWNrKGV2ZW50KTtcbiAgICAgICAgICAgIGlmIChyZW1vdmUpIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHRvUmVtb3ZlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVycy5maWx0ZXIobCA9PiAhdG9SZW1vdmUuaW5jbHVkZXMobCkpO1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5sZW5ndGggPT09IDApIGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudC5uYW1lKTtcbiAgICAgICAgICAgIGVsc2UgZXZlbnRMaXN0ZW5lcnMuc2V0KGV2ZW50Lm5hbWUsIGxpc3RlbmVycyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogUmVnaXN0ZXIgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgbXVsdGlwbGUgdGltZXMgZm9yIGEgc3BlY2lmaWMgZXZlbnQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZWdpc3RlciB0aGUgY2FsbGJhY2sgZm9yLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIHRyaWdnZXJlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3MgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdGhlIGNhbGxiYWNrIGNhbiBiZSBjYWxsZWQgZm9yIHRoZSBldmVudC4gT25jZSB0aGUgbWF4aW11bSBudW1iZXIgaXMgcmVhY2hlZCwgdGhlIGNhbGxiYWNrIHdpbGwgbm8gbG9uZ2VyIGJlIGNhbGxlZC5cbiAqXG4gQHJldHVybiB7ZnVuY3Rpb259IC0gQSBmdW5jdGlvbiB0aGF0LCB3aGVuIGNhbGxlZCwgd2lsbCB1bnJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmcm9tIHRoZSBldmVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudE5hbWUpIHx8IFtdO1xuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xuICAgIGxpc3RlbmVycy5wdXNoKHRoaXNMaXN0ZW5lcik7XG4gICAgZXZlbnRMaXN0ZW5lcnMuc2V0KGV2ZW50TmFtZSwgbGlzdGVuZXJzKTtcbiAgICByZXR1cm4gKCkgPT4gbGlzdGVuZXJPZmYodGhpc0xpc3RlbmVyKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuIHRoZSBzcGVjaWZpZWQgZXZlbnQgb2NjdXJzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFjayAtIFRoZSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZC4gSXQgdGFrZXMgbm8gcGFyYW1ldGVycy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuICovXG5leHBvcnQgZnVuY3Rpb24gT24oZXZlbnROYW1lLCBjYWxsYmFjaykgeyByZXR1cm4gT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAtMSk7IH1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmx5IG9uY2UgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudC5cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGV2ZW50IG9jY3Vycy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHsgcmV0dXJuIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgMSk7IH1cblxuLyoqXG4gKiBSZW1vdmVzIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIgZnJvbSB0aGUgZXZlbnQgbGlzdGVuZXJzIGNvbGxlY3Rpb24uXG4gKiBJZiBhbGwgbGlzdGVuZXJzIGZvciB0aGUgZXZlbnQgYXJlIHJlbW92ZWQsIHRoZSBldmVudCBrZXkgaXMgZGVsZXRlZCBmcm9tIHRoZSBjb2xsZWN0aW9uLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBsaXN0ZW5lciAtIFRoZSBsaXN0ZW5lciB0byBiZSByZW1vdmVkLlxuICovXG5mdW5jdGlvbiBsaXN0ZW5lck9mZihsaXN0ZW5lcikge1xuICAgIGNvbnN0IGV2ZW50TmFtZSA9IGxpc3RlbmVyLmV2ZW50TmFtZTtcbiAgICBsZXQgbGlzdGVuZXJzID0gZXZlbnRMaXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSkuZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuICAgIGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSBldmVudExpc3RlbmVycy5kZWxldGUoZXZlbnROYW1lKTtcbiAgICBlbHNlIGV2ZW50TGlzdGVuZXJzLnNldChldmVudE5hbWUsIGxpc3RlbmVycyk7XG59XG5cblxuLyoqXG4gKiBSZW1vdmVzIGV2ZW50IGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudCBuYW1lcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSBsaXN0ZW5lcnMgZm9yLlxuICogQHBhcmFtIHsuLi5zdHJpbmd9IGFkZGl0aW9uYWxFdmVudE5hbWVzIC0gQWRkaXRpb25hbCBldmVudCBuYW1lcyB0byByZW1vdmUgbGlzdGVuZXJzIGZvci5cbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9mZihldmVudE5hbWUsIC4uLmFkZGl0aW9uYWxFdmVudE5hbWVzKSB7XG4gICAgbGV0IGV2ZW50c1RvUmVtb3ZlID0gW2V2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXNdO1xuICAgIGV2ZW50c1RvUmVtb3ZlLmZvckVhY2goZXZlbnROYW1lID0+IGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudE5hbWUpKTtcbn1cbi8qKlxuICogUmVtb3ZlcyBhbGwgZXZlbnQgbGlzdGVuZXJzLlxuICpcbiAqIEBmdW5jdGlvbiBPZmZBbGxcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gT2ZmQWxsKCkgeyBldmVudExpc3RlbmVycy5jbGVhcigpOyB9XG5cbi8qKlxuICogRW1pdHMgYW4gZXZlbnQgdXNpbmcgdGhlIGdpdmVuIGV2ZW50IG5hbWUuXG4gKlxuICogQHBhcmFtIHtXYWlsc0V2ZW50fSBldmVudCAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBlbWl0LlxuICogQHJldHVybnMge2FueX0gLSBUaGUgcmVzdWx0IG9mIHRoZSBlbWl0dGVkIGV2ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gRW1pdChldmVudCkgeyByZXR1cm4gY2FsbChFbWl0TWV0aG9kLCBldmVudCk7IH1cbiIsICJcbmV4cG9ydCBjb25zdCBFdmVudFR5cGVzID0ge1xuXHRXaW5kb3dzOiB7XG5cdFx0U3lzdGVtVGhlbWVDaGFuZ2VkOiBcIndpbmRvd3M6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdFx0QVBNUG93ZXJTdGF0dXNDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclN0YXR1c0NoYW5nZVwiLFxuXHRcdEFQTVN1c3BlbmQ6IFwid2luZG93czpBUE1TdXNwZW5kXCIsXG5cdFx0QVBNUmVzdW1lQXV0b21hdGljOiBcIndpbmRvd3M6QVBNUmVzdW1lQXV0b21hdGljXCIsXG5cdFx0QVBNUmVzdW1lU3VzcGVuZDogXCJ3aW5kb3dzOkFQTVJlc3VtZVN1c3BlbmRcIixcblx0XHRBUE1Qb3dlclNldHRpbmdDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclNldHRpbmdDaGFuZ2VcIixcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwid2luZG93czpBcHBsaWNhdGlvblN0YXJ0ZWRcIixcblx0XHRXZWJWaWV3TmF2aWdhdGlvbkNvbXBsZXRlZDogXCJ3aW5kb3dzOldlYlZpZXdOYXZpZ2F0aW9uQ29tcGxldGVkXCIsXG5cdFx0V2luZG93SW5hY3RpdmU6IFwid2luZG93czpXaW5kb3dJbmFjdGl2ZVwiLFxuXHRcdFdpbmRvd0FjdGl2ZTogXCJ3aW5kb3dzOldpbmRvd0FjdGl2ZVwiLFxuXHRcdFdpbmRvd0NsaWNrQWN0aXZlOiBcIndpbmRvd3M6V2luZG93Q2xpY2tBY3RpdmVcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcIndpbmRvd3M6V2luZG93RnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1VuRnVsbHNjcmVlbjogXCJ3aW5kb3dzOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwid2luZG93czpXaW5kb3dSZXN0b3JlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwid2luZG93czpXaW5kb3dNaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWluaW1pc2U6IFwid2luZG93czpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2U6IFwid2luZG93czpXaW5kb3dDbG9zZVwiLFxuXHRcdFdpbmRvd1NldEZvY3VzOiBcIndpbmRvd3M6V2luZG93U2V0Rm9jdXNcIixcblx0XHRXaW5kb3dLaWxsRm9jdXM6IFwid2luZG93czpXaW5kb3dLaWxsRm9jdXNcIixcblx0XHRXaW5kb3dEcmFnRHJvcDogXCJ3aW5kb3dzOldpbmRvd0RyYWdEcm9wXCIsXG5cdFx0V2luZG93RHJhZ0VudGVyOiBcIndpbmRvd3M6V2luZG93RHJhZ0VudGVyXCIsXG5cdFx0V2luZG93RHJhZ0xlYXZlOiBcIndpbmRvd3M6V2luZG93RHJhZ0xlYXZlXCIsXG5cdFx0V2luZG93RHJhZ092ZXI6IFwid2luZG93czpXaW5kb3dEcmFnT3ZlclwiLFxuXHR9LFxuXHRNYWM6IHtcblx0XHRBcHBsaWNhdGlvbkRpZEJlY29tZUFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUVmZmVjdGl2ZUFwcGVhcmFuY2VcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUljb246IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlSWNvblwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU2NyZWVuUGFyYW1ldGVyc1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uXCIsXG5cdFx0QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmc6IFwibWFjOkFwcGxpY2F0aW9uRGlkRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25EaWRIaWRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZEhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFJlc2lnbkFjdGl2ZU5vdGlmaWNhdGlvbjogXCJtYWM6QXBwbGljYXRpb25EaWRSZXNpZ25BY3RpdmVOb3RpZmljYXRpb25cIixcblx0XHRBcHBsaWNhdGlvbkRpZFVuaGlkZTogXCJtYWM6QXBwbGljYXRpb25EaWRVbmhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25EaWRVcGRhdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxCZWNvbWVBY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbEJlY29tZUFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEZpbmlzaExhdW5jaGluZzogXCJtYWM6QXBwbGljYXRpb25XaWxsRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsSGlkZTogXCJtYWM6QXBwbGljYXRpb25XaWxsSGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFJlc2lnbkFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVGVybWluYXRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxVbmhpZGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFVuaGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsVXBkYXRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZTogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZSFcIixcblx0XHRBcHBsaWNhdGlvblNob3VsZEhhbmRsZVJlb3BlbjogXCJtYWM6QXBwbGljYXRpb25TaG91bGRIYW5kbGVSZW9wZW4hXCIsXG5cdFx0V2luZG93RGlkQmVjb21lS2V5OiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dEaWRCZWNvbWVNYWluOiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVNYWluXCIsXG5cdFx0V2luZG93RGlkQmVnaW5TaGVldDogXCJtYWM6V2luZG93RGlkQmVnaW5TaGVldFwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUFscGhhOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VBbHBoYVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUJhY2tpbmdMb2NhdGlvbjogXCJtYWM6V2luZG93RGlkQ2hhbmdlQmFja2luZ0xvY2F0aW9uXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQmFja2luZ1Byb3BlcnRpZXM6IFwibWFjOldpbmRvd0RpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOldpbmRvd0RpZENoYW5nZU9jY2x1c2lvblN0YXRlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW46IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2U6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2VQcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5TcGFjZVByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTaGFyaW5nVHlwZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2hhcmluZ1R5cGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUaXRsZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVGl0bGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUb29sYmFyOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VUb29sYmFyXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd0RpZERlbWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dEaWRFbmRTaGVldDogXCJtYWM6V2luZG93RGlkRW5kU2hlZXRcIixcblx0XHRXaW5kb3dEaWRFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd0RpZEVudGVyRnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dEaWRFeGl0RnVsbFNjcmVlbjogXCJtYWM6V2luZG93RGlkRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEV4aXRWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd0RpZEV4cG9zZTogXCJtYWM6V2luZG93RGlkRXhwb3NlXCIsXG5cdFx0V2luZG93RGlkRm9jdXM6IFwibWFjOldpbmRvd0RpZEZvY3VzXCIsXG5cdFx0V2luZG93RGlkTWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJtYWM6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRPcmRlck9mZlNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd0RpZE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dEaWRSZXNpZ25LZXk6IFwibWFjOldpbmRvd0RpZFJlc2lnbktleVwiLFxuXHRcdFdpbmRvd0RpZFJlc2lnbk1haW46IFwibWFjOldpbmRvd0RpZFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwibWFjOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZTogXCJtYWM6V2luZG93RGlkVXBkYXRlXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd0RpZFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRpdGxlOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVRvb2xiYXJcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5XCIsXG5cdFx0V2luZG93U2hvdWxkQ2xvc2U6IFwibWFjOldpbmRvd1Nob3VsZENsb3NlIVwiLFxuXHRcdFdpbmRvd1dpbGxCZWNvbWVLZXk6IFwibWFjOldpbmRvd1dpbGxCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dXaWxsQmVjb21lTWFpbjogXCJtYWM6V2luZG93V2lsbEJlY29tZU1haW5cIixcblx0XHRXaW5kb3dXaWxsQmVnaW5TaGVldDogXCJtYWM6V2luZG93V2lsbEJlZ2luU2hlZXRcIixcblx0XHRXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93V2lsbENsb3NlOiBcIm1hYzpXaW5kb3dXaWxsQ2xvc2VcIixcblx0XHRXaW5kb3dXaWxsRGVtaW5pYXR1cml6ZTogXCJtYWM6V2luZG93V2lsbERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd1dpbGxFbnRlclZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEV4aXRGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyOiBcIm1hYzpXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsRm9jdXNcIixcblx0XHRXaW5kb3dXaWxsTWluaWF0dXJpemU6IFwibWFjOldpbmRvd1dpbGxNaW5pYXR1cml6ZVwiLFxuXHRcdFdpbmRvd1dpbGxNb3ZlOiBcIm1hYzpXaW5kb3dXaWxsTW92ZVwiLFxuXHRcdFdpbmRvd1dpbGxPcmRlck9mZlNjcmVlbjogXCJtYWM6V2luZG93V2lsbE9yZGVyT2ZmU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd1dpbGxPcmRlck9uU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbFJlc2lnbk1haW46IFwibWFjOldpbmRvd1dpbGxSZXNpZ25NYWluXCIsXG5cdFx0V2luZG93V2lsbFJlc2l6ZTogXCJtYWM6V2luZG93V2lsbFJlc2l6ZVwiLFxuXHRcdFdpbmRvd1dpbGxVbmZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsVW5mb2N1c1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVBbHBoYVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3I6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXM6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllc1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVTaGFkb3dcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlVGl0bGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVUb29sYmFyOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVG9vbGJhclwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd1dpbGxVc2VTdGFuZGFyZEZyYW1lOiBcIm1hYzpXaW5kb3dXaWxsVXNlU3RhbmRhcmRGcmFtZVwiLFxuXHRcdE1lbnVXaWxsT3BlbjogXCJtYWM6TWVudVdpbGxPcGVuXCIsXG5cdFx0TWVudURpZE9wZW46IFwibWFjOk1lbnVEaWRPcGVuXCIsXG5cdFx0TWVudURpZENsb3NlOiBcIm1hYzpNZW51RGlkQ2xvc2VcIixcblx0XHRNZW51V2lsbFNlbmRBY3Rpb246IFwibWFjOk1lbnVXaWxsU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVXaWxsSGlnaGxpZ2h0SXRlbTogXCJtYWM6TWVudVdpbGxIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudURpZEhpZ2hsaWdodEl0ZW06IFwibWFjOk1lbnVEaWRIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudVdpbGxEaXNwbGF5SXRlbTogXCJtYWM6TWVudVdpbGxEaXNwbGF5SXRlbVwiLFxuXHRcdE1lbnVEaWREaXNwbGF5SXRlbTogXCJtYWM6TWVudURpZERpc3BsYXlJdGVtXCIsXG5cdFx0TWVudVdpbGxBZGRJdGVtOiBcIm1hYzpNZW51V2lsbEFkZEl0ZW1cIixcblx0XHRNZW51RGlkQWRkSXRlbTogXCJtYWM6TWVudURpZEFkZEl0ZW1cIixcblx0XHRNZW51V2lsbFJlbW92ZUl0ZW06IFwibWFjOk1lbnVXaWxsUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVEaWRSZW1vdmVJdGVtOiBcIm1hYzpNZW51RGlkUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVXaWxsQmVnaW5UcmFja2luZzogXCJtYWM6TWVudVdpbGxCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudURpZEJlZ2luVHJhY2tpbmc6IFwibWFjOk1lbnVEaWRCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxFbmRUcmFja2luZzogXCJtYWM6TWVudVdpbGxFbmRUcmFja2luZ1wiLFxuXHRcdE1lbnVEaWRFbmRUcmFja2luZzogXCJtYWM6TWVudURpZEVuZFRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxVcGRhdGU6IFwibWFjOk1lbnVXaWxsVXBkYXRlXCIsXG5cdFx0TWVudURpZFVwZGF0ZTogXCJtYWM6TWVudURpZFVwZGF0ZVwiLFxuXHRcdE1lbnVXaWxsUG9wVXA6IFwibWFjOk1lbnVXaWxsUG9wVXBcIixcblx0XHRNZW51RGlkUG9wVXA6IFwibWFjOk1lbnVEaWRQb3BVcFwiLFxuXHRcdE1lbnVXaWxsU2VuZEFjdGlvblRvSXRlbTogXCJtYWM6TWVudVdpbGxTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0TWVudURpZFNlbmRBY3Rpb25Ub0l0ZW06IFwibWFjOk1lbnVEaWRTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0V2ViVmlld0RpZFN0YXJ0UHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkU3RhcnRQcm92aXNpb25hbE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZENvbW1pdE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRDb21taXROYXZpZ2F0aW9uXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZFwiLFxuXHRcdFdpbmRvd0ZpbGVEcmFnZ2luZ1BlcmZvcm1lZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nUGVyZm9ybWVkXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRXhpdGVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdFeGl0ZWRcIixcblx0fSxcblx0TGludXg6IHtcblx0XHRTeXN0ZW1UaGVtZUNoYW5nZWQ6IFwibGludXg6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdH0sXG5cdENvbW1vbjoge1xuXHRcdEFwcGxpY2F0aW9uU3RhcnRlZDogXCJjb21tb246QXBwbGljYXRpb25TdGFydGVkXCIsXG5cdFx0V2luZG93TWF4aW1pc2U6IFwiY29tbW9uOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJjb21tb246V2luZG93VW5NYXhpbWlzZVwiLFxuXHRcdFdpbmRvd0Z1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd0Z1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dVbkZ1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwiY29tbW9uOldpbmRvd1Jlc3RvcmVcIixcblx0XHRXaW5kb3dNaW5pbWlzZTogXCJjb21tb246V2luZG93TWluaW1pc2VcIixcblx0XHRXaW5kb3dVbk1pbmltaXNlOiBcImNvbW1vbjpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2luZzogXCJjb21tb246V2luZG93Q2xvc2luZ1wiLFxuXHRcdFdpbmRvd1pvb206IFwiY29tbW9uOldpbmRvd1pvb21cIixcblx0XHRXaW5kb3dab29tSW46IFwiY29tbW9uOldpbmRvd1pvb21JblwiLFxuXHRcdFdpbmRvd1pvb21PdXQ6IFwiY29tbW9uOldpbmRvd1pvb21PdXRcIixcblx0XHRXaW5kb3dab29tUmVzZXQ6IFwiY29tbW9uOldpbmRvd1pvb21SZXNldFwiLFxuXHRcdFdpbmRvd0ZvY3VzOiBcImNvbW1vbjpXaW5kb3dGb2N1c1wiLFxuXHRcdFdpbmRvd0xvc3RGb2N1czogXCJjb21tb246V2luZG93TG9zdEZvY3VzXCIsXG5cdFx0V2luZG93U2hvdzogXCJjb21tb246V2luZG93U2hvd1wiLFxuXHRcdFdpbmRvd0hpZGU6IFwiY29tbW9uOldpbmRvd0hpZGVcIixcblx0XHRXaW5kb3dEUElDaGFuZ2VkOiBcImNvbW1vbjpXaW5kb3dEUElDaGFuZ2VkXCIsXG5cdFx0V2luZG93RmlsZXNEcm9wcGVkOiBcImNvbW1vbjpXaW5kb3dGaWxlc0Ryb3BwZWRcIixcblx0XHRXaW5kb3dSdW50aW1lUmVhZHk6IFwiY29tbW9uOldpbmRvd1J1bnRpbWVSZWFkeVwiLFxuXHRcdFRoZW1lQ2hhbmdlZDogXCJjb21tb246VGhlbWVDaGFuZ2VkXCIsXG5cdH0sXG59O1xuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gT3BlbkZpbGVEaWFsb2dPcHRpb25zXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DaG9vc2VEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNob3Nlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZUZpbGVzXSAtIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ3JlYXRlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbU2hvd0hpZGRlbkZpbGVzXSAtIEluZGljYXRlcyBpZiBoaWRkZW4gZmlsZXMgc2hvdWxkIGJlIHNob3duLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbUmVzb2x2ZXNBbGlhc2VzXSAtIEluZGljYXRlcyBpZiBhbGlhc2VzIHNob3VsZCBiZSByZXNvbHZlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c011bHRpcGxlU2VsZWN0aW9uXSAtIEluZGljYXRlcyBpZiBtdWx0aXBsZSBzZWxlY3Rpb24gaXMgYWxsb3dlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0hpZGVFeHRlbnNpb25dIC0gSW5kaWNhdGVzIGlmIHRoZSBleHRlbnNpb24gc2hvdWxkIGJlIGhpZGRlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhblNlbGVjdEhpZGRlbkV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGV4dGVuc2lvbnMgY2FuIGJlIHNlbGVjdGVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZmlsZSBwYWNrYWdlcyBzaG91bGQgYmUgdHJlYXRlZCBhcyBkaXJlY3Rvcmllcy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c090aGVyRmlsZXR5cGVzXSAtIEluZGljYXRlcyBpZiBvdGhlciBmaWxlIHR5cGVzIGFyZSBhbGxvd2VkLlxuICogQHByb3BlcnR5IHtGaWxlRmlsdGVyW119IFtGaWx0ZXJzXSAtIEFycmF5IG9mIGZpbGUgZmlsdGVycy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGl0bGUgb2YgdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbTWVzc2FnZV0gLSBNZXNzYWdlIHRvIHNob3cgaW4gdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbQnV0dG9uVGV4dF0gLSBUZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRGlyZWN0b3J5XSAtIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtEZXRhY2hlZF0gLSBJbmRpY2F0ZXMgaWYgdGhlIGRpYWxvZyBzaG91bGQgYXBwZWFyIGRldGFjaGVkIGZyb20gdGhlIG1haW4gd2luZG93LlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBTYXZlRmlsZURpYWxvZ09wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRmlsZW5hbWVdIC0gRGVmYXVsdCBmaWxlbmFtZSB0byB1c2UgaW4gdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZURpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBkaXJlY3RvcmllcyBjYW4gYmUgY2hvc2VuLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ2hvb3NlRmlsZXNdIC0gSW5kaWNhdGVzIGlmIGZpbGVzIGNhbiBiZSBjaG9zZW4uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DcmVhdGVEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNyZWF0ZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtTaG93SGlkZGVuRmlsZXNdIC0gSW5kaWNhdGVzIGlmIGhpZGRlbiBmaWxlcyBzaG91bGQgYmUgc2hvd24uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtSZXNvbHZlc0FsaWFzZXNdIC0gSW5kaWNhdGVzIGlmIGFsaWFzZXMgc2hvdWxkIGJlIHJlc29sdmVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQWxsb3dzTXVsdGlwbGVTZWxlY3Rpb25dIC0gSW5kaWNhdGVzIGlmIG11bHRpcGxlIHNlbGVjdGlvbiBpcyBhbGxvd2VkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbSGlkZUV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgdGhlIGV4dGVuc2lvbiBzaG91bGQgYmUgaGlkZGVuLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuU2VsZWN0SGlkZGVuRXh0ZW5zaW9uXSAtIEluZGljYXRlcyBpZiBoaWRkZW4gZXh0ZW5zaW9ucyBjYW4gYmUgc2VsZWN0ZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtUcmVhdHNGaWxlUGFja2FnZXNBc0RpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBmaWxlIHBhY2thZ2VzIHNob3VsZCBiZSB0cmVhdGVkIGFzIGRpcmVjdG9yaWVzLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQWxsb3dzT3RoZXJGaWxldHlwZXNdIC0gSW5kaWNhdGVzIGlmIG90aGVyIGZpbGUgdHlwZXMgYXJlIGFsbG93ZWQuXG4gKiBAcHJvcGVydHkge0ZpbGVGaWx0ZXJbXX0gW0ZpbHRlcnNdIC0gQXJyYXkgb2YgZmlsZSBmaWx0ZXJzLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtUaXRsZV0gLSBUaXRsZSBvZiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtNZXNzYWdlXSAtIE1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtCdXR0b25UZXh0XSAtIFRleHQgdG8gZGlzcGxheSBvbiB0aGUgYnV0dG9uLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtEaXJlY3RvcnldIC0gRGlyZWN0b3J5IHRvIG9wZW4gaW4gdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0RldGFjaGVkXSAtIEluZGljYXRlcyBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cuXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBNZXNzYWdlRGlhbG9nT3B0aW9uc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IFtUaXRsZV0gLSBUaGUgdGl0bGUgb2YgdGhlIGRpYWxvZyB3aW5kb3cuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW01lc3NhZ2VdIC0gVGhlIG1haW4gbWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge0J1dHRvbltdfSBbQnV0dG9uc10gLSBBcnJheSBvZiBidXR0b24gb3B0aW9ucyB0byBzaG93IGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtEZXRhY2hlZF0gLSBUcnVlIGlmIHRoZSBkaWFsb2cgc2hvdWxkIGFwcGVhciBkZXRhY2hlZCBmcm9tIHRoZSBtYWluIHdpbmRvdyAoaWYgYXBwbGljYWJsZSkuXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBCdXR0b25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbTGFiZWxdIC0gVGV4dCB0aGF0IGFwcGVhcnMgd2l0aGluIHRoZSBidXR0b24uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtJc0NhbmNlbF0gLSBUcnVlIGlmIHRoZSBidXR0b24gc2hvdWxkIGNhbmNlbCBhbiBvcGVyYXRpb24gd2hlbiBjbGlja2VkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbSXNEZWZhdWx0XSAtIFRydWUgaWYgdGhlIGJ1dHRvbiBzaG91bGQgYmUgdGhlIGRlZmF1bHQgYWN0aW9uIHdoZW4gdGhlIHVzZXIgcHJlc3NlcyBlbnRlci5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEZpbGVGaWx0ZXJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRGlzcGxheU5hbWVdIC0gRGlzcGxheSBuYW1lIGZvciB0aGUgZmlsdGVyLCBpdCBjb3VsZCBiZSBcIlRleHQgRmlsZXNcIiwgXCJJbWFnZXNcIiBldGMuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW1BhdHRlcm5dIC0gUGF0dGVybiB0byBtYXRjaCBmb3IgdGhlIGZpbHRlciwgZS5nLiBcIioudHh0OyoubWRcIiBmb3IgdGV4dCBtYXJrZG93biBmaWxlcy5cbiAqL1xuXG4vLyBzZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLmRpYWxvZ0Vycm9yQ2FsbGJhY2sgPSBkaWFsb2dFcnJvckNhbGxiYWNrO1xud2luZG93Ll93YWlscy5kaWFsb2dSZXN1bHRDYWxsYmFjayA9IGRpYWxvZ1Jlc3VsdENhbGxiYWNrO1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZC9ub24tc2VjdXJlJztcblxuLy8gRGVmaW5lIGNvbnN0YW50cyBmcm9tIHRoZSBgbWV0aG9kc2Agb2JqZWN0IGluIFRpdGxlIENhc2VcbmNvbnN0IERpYWxvZ0luZm8gPSAwO1xuY29uc3QgRGlhbG9nV2FybmluZyA9IDE7XG5jb25zdCBEaWFsb2dFcnJvciA9IDI7XG5jb25zdCBEaWFsb2dRdWVzdGlvbiA9IDM7XG5jb25zdCBEaWFsb2dPcGVuRmlsZSA9IDQ7XG5jb25zdCBEaWFsb2dTYXZlRmlsZSA9IDU7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkRpYWxvZywgJycpO1xuY29uc3QgZGlhbG9nUmVzcG9uc2VzID0gbmV3IE1hcCgpO1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBpZCB0aGF0IGlzIG5vdCBwcmVzZW50IGluIGRpYWxvZ1Jlc3BvbnNlcy5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IHVuaXF1ZSBpZFxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZUlEKCkge1xuICAgIGxldCByZXN1bHQ7XG4gICAgZG8ge1xuICAgICAgICByZXN1bHQgPSBuYW5vaWQoKTtcbiAgICB9IHdoaWxlIChkaWFsb2dSZXNwb25zZXMuaGFzKHJlc3VsdCkpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogU2hvd3MgYSBkaWFsb2cgb2Ygc3BlY2lmaWVkIHR5cGUgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0eXBlIC0gdHlwZSBvZiBkaWFsb2dcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN8T3BlbkZpbGVEaWFsb2dPcHRpb25zfFNhdmVGaWxlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIG9wdGlvbnMgZm9yIHRoZSBkaWFsb2dcbiAqIEByZXR1cm5zIHtQcm9taXNlfSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCByZXN1bHQgb2YgZGlhbG9nXG4gKi9cbmZ1bmN0aW9uIGRpYWxvZyh0eXBlLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBpZCA9IGdlbmVyYXRlSUQoKTtcbiAgICBvcHRpb25zW1wiZGlhbG9nLWlkXCJdID0gaWQ7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgZGlhbG9nUmVzcG9uc2VzLnNldChpZCwge3Jlc29sdmUsIHJlamVjdH0pO1xuICAgICAgICBjYWxsKHR5cGUsIG9wdGlvbnMpLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBIYW5kbGVzIHRoZSBjYWxsYmFjayBmcm9tIGEgZGlhbG9nLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFRoZSBJRCBvZiB0aGUgZGlhbG9nIHJlc3BvbnNlLlxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGEgLSBUaGUgZGF0YSByZWNlaXZlZCBmcm9tIHRoZSBkaWFsb2cuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGlzSlNPTiAtIEZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSBkYXRhIGlzIGluIEpTT04gZm9ybWF0LlxuICpcbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cbiAqL1xuZnVuY3Rpb24gZGlhbG9nUmVzdWx0Q2FsbGJhY2soaWQsIGRhdGEsIGlzSlNPTikge1xuICAgIGxldCBwID0gZGlhbG9nUmVzcG9uc2VzLmdldChpZCk7XG4gICAgaWYgKHApIHtcbiAgICAgICAgaWYgKGlzSlNPTikge1xuICAgICAgICAgICAgcC5yZXNvbHZlKEpTT04ucGFyc2UoZGF0YSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcC5yZXNvbHZlKGRhdGEpO1xuICAgICAgICB9XG4gICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBDYWxsYmFjayBmdW5jdGlvbiBmb3IgaGFuZGxpbmcgZXJyb3JzIGluIGRpYWxvZy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBUaGUgaWQgb2YgdGhlIGRpYWxvZyByZXNwb25zZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gZGlhbG9nRXJyb3JDYWxsYmFjayhpZCwgbWVzc2FnZSkge1xuICAgIGxldCBwID0gZGlhbG9nUmVzcG9uc2VzLmdldChpZCk7XG4gICAgaWYgKHApIHtcbiAgICAgICAgcC5yZWplY3QobWVzc2FnZSk7XG4gICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgIH1cbn1cblxuXG4vLyBSZXBsYWNlIGBtZXRob2RzYCB3aXRoIGNvbnN0YW50cyBpbiBUaXRsZSBDYXNlXG5cbi8qKlxuICogQHBhcmFtIHtNZXNzYWdlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcbiAqL1xuZXhwb3J0IGNvbnN0IEluZm8gPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ0luZm8sIG9wdGlvbnMpO1xuXG4vKipcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gLSBUaGUgbGFiZWwgb2YgdGhlIGJ1dHRvbiBwcmVzc2VkXG4gKi9cbmV4cG9ydCBjb25zdCBXYXJuaW5nID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dXYXJuaW5nLCBvcHRpb25zKTtcblxuLyoqXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gVGhlIGxhYmVsIG9mIHRoZSBidXR0b24gcHJlc3NlZFxuICovXG5leHBvcnQgY29uc3QgRXJyb3IgPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ0Vycm9yLCBvcHRpb25zKTtcblxuLyoqXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gVGhlIGxhYmVsIG9mIHRoZSBidXR0b24gcHJlc3NlZFxuICovXG5leHBvcnQgY29uc3QgUXVlc3Rpb24gPSAob3B0aW9ucykgPT4gZGlhbG9nKERpYWxvZ1F1ZXN0aW9uLCBvcHRpb25zKTtcblxuLyoqXG4gKiBAcGFyYW0ge09wZW5GaWxlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmdbXXxzdHJpbmc+fSBSZXR1cm5zIHNlbGVjdGVkIGZpbGUgb3IgbGlzdCBvZiBmaWxlcy4gUmV0dXJucyBibGFuayBzdHJpbmcgaWYgbm8gZmlsZSBpcyBzZWxlY3RlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IE9wZW5GaWxlID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dPcGVuRmlsZSwgb3B0aW9ucyk7XG5cbi8qKlxuICogQHBhcmFtIHtTYXZlRmlsZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gUmV0dXJucyB0aGUgc2VsZWN0ZWQgZmlsZS4gUmV0dXJucyBibGFuayBzdHJpbmcgaWYgbm8gZmlsZSBpcyBzZWxlY3RlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IFNhdmVGaWxlID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dTYXZlRmlsZSwgb3B0aW9ucyk7XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZVwiO1xuaW1wb3J0IHsgbmFub2lkIH0gZnJvbSAnbmFub2lkL25vbi1zZWN1cmUnO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLmNhbGxSZXN1bHRIYW5kbGVyID0gcmVzdWx0SGFuZGxlcjtcbndpbmRvdy5fd2FpbHMuY2FsbEVycm9ySGFuZGxlciA9IGVycm9ySGFuZGxlcjtcblxuXG5jb25zdCBDYWxsQmluZGluZyA9IDA7XG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5DYWxsLCAnJyk7XG5jb25zdCBjYW5jZWxDYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5DYW5jZWxDYWxsLCAnJyk7XG5sZXQgY2FsbFJlc3BvbnNlcyA9IG5ldyBNYXAoKTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgSUQgdXNpbmcgdGhlIG5hbm9pZCBsaWJyYXJ5LlxuICpcbiAqIEByZXR1cm4ge3N0cmluZ30gLSBBIHVuaXF1ZSBJRCB0aGF0IGRvZXMgbm90IGV4aXN0IGluIHRoZSBjYWxsUmVzcG9uc2VzIHNldC5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVJRCgpIHtcbiAgICBsZXQgcmVzdWx0O1xuICAgIGRvIHtcbiAgICAgICAgcmVzdWx0ID0gbmFub2lkKCk7XG4gICAgfSB3aGlsZSAoY2FsbFJlc3BvbnNlcy5oYXMocmVzdWx0KSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBIYW5kbGVzIHRoZSByZXN1bHQgb2YgYSBjYWxsIHJlcXVlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSByZXF1ZXN0IHRvIGhhbmRsZSB0aGUgcmVzdWx0IGZvci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhIC0gVGhlIHJlc3VsdCBkYXRhIG9mIHRoZSByZXF1ZXN0LlxuICogQHBhcmFtIHtib29sZWFufSBpc0pTT04gLSBJbmRpY2F0ZXMgd2hldGhlciB0aGUgZGF0YSBpcyBKU09OIG9yIG5vdC5cbiAqXG4gKiBAcmV0dXJuIHt1bmRlZmluZWR9IC0gVGhpcyBtZXRob2QgZG9lcyBub3QgcmV0dXJuIGFueSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gcmVzdWx0SGFuZGxlcihpZCwgZGF0YSwgaXNKU09OKSB7XG4gICAgY29uc3QgcHJvbWlzZUhhbmRsZXIgPSBnZXRBbmREZWxldGVSZXNwb25zZShpZCk7XG4gICAgaWYgKHByb21pc2VIYW5kbGVyKSB7XG4gICAgICAgIHByb21pc2VIYW5kbGVyLnJlc29sdmUoaXNKU09OID8gSlNPTi5wYXJzZShkYXRhKSA6IGRhdGEpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBIYW5kbGVzIHRoZSBlcnJvciBmcm9tIGEgY2FsbCByZXF1ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFRoZSBpZCBvZiB0aGUgcHJvbWlzZSBoYW5kbGVyLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBUaGUgZXJyb3IgbWVzc2FnZSB0byByZWplY3QgdGhlIHByb21pc2UgaGFuZGxlciB3aXRoLlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGVycm9ySGFuZGxlcihpZCwgbWVzc2FnZSkge1xuICAgIGNvbnN0IHByb21pc2VIYW5kbGVyID0gZ2V0QW5kRGVsZXRlUmVzcG9uc2UoaWQpO1xuICAgIGlmIChwcm9taXNlSGFuZGxlcikge1xuICAgICAgICBwcm9taXNlSGFuZGxlci5yZWplY3QobWVzc2FnZSk7XG4gICAgfVxufVxuXG4vKipcbiAqIFJldHJpZXZlcyBhbmQgcmVtb3ZlcyB0aGUgcmVzcG9uc2UgYXNzb2NpYXRlZCB3aXRoIHRoZSBnaXZlbiBJRCBmcm9tIHRoZSBjYWxsUmVzcG9uc2VzIG1hcC5cbiAqXG4gKiBAcGFyYW0ge2FueX0gaWQgLSBUaGUgSUQgb2YgdGhlIHJlc3BvbnNlIHRvIGJlIHJldHJpZXZlZCBhbmQgcmVtb3ZlZC5cbiAqXG4gKiBAcmV0dXJucyB7YW55fSBUaGUgcmVzcG9uc2Ugb2JqZWN0IGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gSUQuXG4gKi9cbmZ1bmN0aW9uIGdldEFuZERlbGV0ZVJlc3BvbnNlKGlkKSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBjYWxsUmVzcG9uc2VzLmdldChpZCk7XG4gICAgY2FsbFJlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgIHJldHVybiByZXNwb25zZTtcbn1cblxuLyoqXG4gKiBFeGVjdXRlcyBhIGNhbGwgdXNpbmcgdGhlIHByb3ZpZGVkIHR5cGUgYW5kIG9wdGlvbnMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSB0eXBlIC0gVGhlIHR5cGUgb2YgY2FsbCB0byBleGVjdXRlLlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSAtIEFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgdGhlIGNhbGwuXG4gKiBAcmV0dXJuIHtQcm9taXNlfSAtIEEgcHJvbWlzZSB0aGF0IHdpbGwgYmUgcmVzb2x2ZWQgb3IgcmVqZWN0ZWQgYmFzZWQgb24gdGhlIHJlc3VsdCBvZiB0aGUgY2FsbC4gSXQgYWxzbyBoYXMgYSBjYW5jZWwgbWV0aG9kIHRvIGNhbmNlbCBhIGxvbmcgcnVubmluZyByZXF1ZXN0LlxuICovXG5mdW5jdGlvbiBjYWxsQmluZGluZyh0eXBlLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBpZCA9IGdlbmVyYXRlSUQoKTtcbiAgICBjb25zdCBkb0NhbmNlbCA9ICgpID0+IHsgY2FuY2VsQ2FsbCh0eXBlLCB7XCJjYWxsLWlkXCI6IGlkfSkgfTtcbiAgICB2YXIgcXVldWVkQ2FuY2VsID0gZmFsc2UsIGNhbGxSdW5uaW5nID0gZmFsc2U7XG4gICAgdmFyIHAgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIG9wdGlvbnNbXCJjYWxsLWlkXCJdID0gaWQ7XG4gICAgICAgIGNhbGxSZXNwb25zZXMuc2V0KGlkLCB7IHJlc29sdmUsIHJlamVjdCB9KTtcbiAgICAgICAgY2FsbCh0eXBlLCBvcHRpb25zKS5cbiAgICAgICAgICAgIHRoZW4oKF8pID0+IHtcbiAgICAgICAgICAgICAgICBjYWxsUnVubmluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgaWYgKHF1ZXVlZENhbmNlbCkge1xuICAgICAgICAgICAgICAgICAgICBkb0NhbmNlbCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLlxuICAgICAgICAgICAgY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICBjYWxsUmVzcG9uc2VzLmRlbGV0ZShpZCk7XG4gICAgICAgICAgICB9KTtcbiAgICB9KTtcbiAgICBwLmNhbmNlbCA9ICgpID0+IHtcbiAgICAgICAgaWYgKGNhbGxSdW5uaW5nKSB7XG4gICAgICAgICAgICBkb0NhbmNlbCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcXVldWVkQ2FuY2VsID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgXG4gICAgcmV0dXJuIHA7XG59XG5cbi8qKlxuICogQ2FsbCBtZXRob2QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBUaGUgb3B0aW9ucyBmb3IgdGhlIG1ldGhvZC5cbiAqIEByZXR1cm5zIHtPYmplY3R9IC0gVGhlIHJlc3VsdCBvZiB0aGUgY2FsbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhbGwob3B0aW9ucykge1xuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywgb3B0aW9ucyk7XG59XG5cbi8qKlxuICogRXhlY3V0ZXMgYSBtZXRob2QgYnkgbmFtZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgaW4gdGhlIGZvcm1hdCAncGFja2FnZS5zdHJ1Y3QubWV0aG9kJy5cbiAqIEBwYXJhbSB7Li4uKn0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBuYW1lIGlzIG5vdCBhIHN0cmluZyBvciBpcyBub3QgaW4gdGhlIGNvcnJlY3QgZm9ybWF0LlxuICogQHJldHVybnMgeyp9IFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBleGVjdXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBCeU5hbWUobmFtZSwgLi4uYXJncykge1xuICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gXCJzdHJpbmdcIiB8fCBuYW1lLnNwbGl0KFwiLlwiKS5sZW5ndGggIT09IDMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FsbEJ5TmFtZSByZXF1aXJlcyBhIHN0cmluZyBpbiB0aGUgZm9ybWF0ICdwYWNrYWdlLnN0cnVjdC5tZXRob2QnXCIpO1xuICAgIH1cbiAgICBsZXQgW3BhY2thZ2VOYW1lLCBzdHJ1Y3ROYW1lLCBtZXRob2ROYW1lXSA9IG5hbWUuc3BsaXQoXCIuXCIpO1xuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywge1xuICAgICAgICBwYWNrYWdlTmFtZSxcbiAgICAgICAgc3RydWN0TmFtZSxcbiAgICAgICAgbWV0aG9kTmFtZSxcbiAgICAgICAgYXJnc1xuICAgIH0pO1xufVxuXG4vKipcbiAqIENhbGxzIGEgbWV0aG9kIGJ5IGl0cyBJRCB3aXRoIHRoZSBzcGVjaWZpZWQgYXJndW1lbnRzLlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBtZXRob2RJRCAtIFRoZSBJRCBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXG4gKiBAcGFyYW0gey4uLip9IGFyZ3MgLSBUaGUgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIG1ldGhvZC5cbiAqIEByZXR1cm4geyp9IC0gVGhlIHJlc3VsdCBvZiB0aGUgbWV0aG9kIGNhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBCeUlEKG1ldGhvZElELCAuLi5hcmdzKSB7XG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XG4gICAgICAgIG1ldGhvZElELFxuICAgICAgICBhcmdzXG4gICAgfSk7XG59XG5cbi8qKlxuICogQ2FsbHMgYSBtZXRob2Qgb24gYSBwbHVnaW4uXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHBsdWdpbk5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcGx1Z2luLlxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXG4gKiBAcGFyYW0gey4uLip9IGFyZ3MgLSBUaGUgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIG1ldGhvZC5cbiAqIEByZXR1cm5zIHsqfSAtIFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gUGx1Z2luKHBsdWdpbk5hbWUsIG1ldGhvZE5hbWUsIC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gY2FsbEJpbmRpbmcoQ2FsbEJpbmRpbmcsIHtcbiAgICAgICAgcGFja2FnZU5hbWU6IFwid2FpbHMtcGx1Z2luc1wiLFxuICAgICAgICBzdHJ1Y3ROYW1lOiBwbHVnaW5OYW1lLFxuICAgICAgICBtZXRob2ROYW1lLFxuICAgICAgICBhcmdzXG4gICAgfSk7XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7ZGVidWdMb2d9IGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9sb2dcIjtcblxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG5cbmltcG9ydCAqIGFzIEFwcGxpY2F0aW9uIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9hcHBsaWNhdGlvblwiO1xuaW1wb3J0ICogYXMgQnJvd3NlciBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvYnJvd3NlclwiO1xuaW1wb3J0ICogYXMgQ2xpcGJvYXJkIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9jbGlwYm9hcmRcIjtcbmltcG9ydCAqIGFzIENvbnRleHRNZW51IGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9jb250ZXh0bWVudVwiO1xuaW1wb3J0ICogYXMgRHJhZyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZHJhZ1wiO1xuaW1wb3J0ICogYXMgRmxhZ3MgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2ZsYWdzXCI7XG5pbXBvcnQgKiBhcyBTY3JlZW5zIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9zY3JlZW5zXCI7XG5pbXBvcnQgKiBhcyBTeXN0ZW0gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbVwiO1xuaW1wb3J0ICogYXMgV2luZG93IGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy93aW5kb3dcIjtcbmltcG9ydCAqIGFzIFdNTCBmcm9tICcuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy93bWwnO1xuaW1wb3J0ICogYXMgRXZlbnRzIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9ldmVudHNcIjtcbmltcG9ydCAqIGFzIERpYWxvZ3MgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RpYWxvZ3NcIjtcbmltcG9ydCAqIGFzIENhbGwgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NhbGxzXCI7XG5pbXBvcnQge2ludm9rZX0gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3N5c3RlbVwiO1xuXG4vKioqXG4gVGhpcyB0ZWNobmlxdWUgZm9yIHByb3BlciBsb2FkIGRldGVjdGlvbiBpcyB0YWtlbiBmcm9tIEhUTVg6XG5cbiBCU0QgMi1DbGF1c2UgTGljZW5zZVxuXG4gQ29weXJpZ2h0IChjKSAyMDIwLCBCaWcgU2t5IFNvZnR3YXJlXG4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dFxuIG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG5cbiAyLiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvblxuIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG4gVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCJcbiBBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFXG4gSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXG4gRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRVxuIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMXG4gREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1JcbiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUlxuIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksXG4gT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0VcbiBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuXG4gKioqL1xuXG53aW5kb3cuX3dhaWxzLmludm9rZT1pbnZva2U7XG5cbndpbmRvdy53YWlscyA9IHdpbmRvdy53YWlscyB8fCB7fTtcbndpbmRvdy53YWlscy5BcHBsaWNhdGlvbiA9IEFwcGxpY2F0aW9uO1xud2luZG93LndhaWxzLkJyb3dzZXIgPSBCcm93c2VyO1xud2luZG93LndhaWxzLkNhbGwgPSBDYWxsO1xud2luZG93LndhaWxzLkNsaXBib2FyZCA9IENsaXBib2FyZDtcbndpbmRvdy53YWlscy5EaWFsb2dzID0gRGlhbG9ncztcbndpbmRvdy53YWlscy5FdmVudHMgPSBFdmVudHM7XG53aW5kb3cud2FpbHMuRmxhZ3MgPSBGbGFncztcbndpbmRvdy53YWlscy5TY3JlZW5zID0gU2NyZWVucztcbndpbmRvdy53YWlscy5TeXN0ZW0gPSBTeXN0ZW07XG53aW5kb3cud2FpbHMuV2luZG93ID0gV2luZG93O1xud2luZG93LndhaWxzLldNTCA9IFdNTDtcblxuXG5sZXQgaXNSZWFkeSA9IGZhbHNlXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZnVuY3Rpb24oKSB7XG4gICAgaXNSZWFkeSA9IHRydWVcbiAgICB3aW5kb3cuX3dhaWxzLmludm9rZSgnd2FpbHM6cnVudGltZTpyZWFkeScpO1xuICAgIGlmKERFQlVHKSB7XG4gICAgICAgIGRlYnVnTG9nKFwiV2FpbHMgUnVudGltZSBMb2FkZWRcIik7XG4gICAgfVxufSlcblxuZnVuY3Rpb24gd2hlblJlYWR5KGZuKSB7XG4gICAgaWYgKGlzUmVhZHkgfHwgZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2NvbXBsZXRlJykge1xuICAgICAgICBmbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCBmbik7XG4gICAgfVxufVxuXG53aGVuUmVhZHkoKCkgPT4ge1xuICAgIFdNTC5SZWxvYWQoKTtcbn0pO1xuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7QUFLTyxXQUFTLFNBQVMsU0FBUztBQUU5QixZQUFRO0FBQUEsTUFDSixrQkFBa0IsVUFBVTtBQUFBLE1BQzVCO0FBQUEsTUFDQTtB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cEMsMENBQTBDO0FBQUEsTUFDMUMsK0JBQStCO0FBQUEsTUFDL0Isb0JBQW9CO0FBQUEsTUFDcEIsd0NBQXdDO0FBQUEsTUFDeEMsc0JBQXNCO0FBQUEsTUFDdEIsc0JBQXNCO0FBQUEsTUFDdEIsNkJBQTZCO0FBQUEsTUFDN0IsZ0NBQWdDO0FBQUEsTUFDaEMscUJBQXFCO0FBQUEsTUFDckIsNkJBQTZCO0FBQUEsTUFDN0IsMEJBQTBCO0FBQUEsTUFDMUIsdUJBQXVCO0FBQUEsTUFDdkIsdUJBQXVCO0FBQUEsTUFDdkIsMkJBQTJCO0FBQUEsTUFDM0IsK0JBQStCO0FBQUEsTUFDL0Isb0JBQW9CO0FBQUEsTUFDcEIscUJBQXFCO0FBQUEsTUFDckIscUJBQXFCO0FBQUEsTUFDckIsc0JBQXNCO0FBQUEsTUFDdEIsZ0NBQWdDO0FBQUEsTUFDaEMsa0NBQWtDO0FBQUEsTUFDbEMsbUNBQW1DO0FBQUEsTUFDbkMsb0NBQW9DO0FBQUEsTUFDcEMsK0JBQStCO0FBQUEsTUFDL0IsNkJBQTZCO0FBQUEsTUFDN0IsdUJBQXVCO0FBQUEsTUFDdkIsaUNBQWlDO0FBQUEsTUFDakMsOEJBQThCO0FBQUEsTUFDOUIsNEJBQTRCO0FBQUEsTUFDNUIsc0NBQXNDO0FBQUEsTUFDdEMsNEJBQTRCO0FBQUEsTUFDNUIsc0JBQXNCO0FBQUEsTUFDdEIsa0NBQWtDO0FBQUEsTUFDbEMsc0JBQXNCO0FBQUEsTUFDdEIsd0JBQXdCO0FBQUEsTUFDeEIsMkJBQTJCO0FBQUEsTUFDM0Isd0JBQXdCO0FBQUEsTUFDeEIsbUJBQW1CO0FBQUEsTUFDbkIsMEJBQTBCO0FBQUEsTUFDMUIsOEJBQThCO0FBQUEsTUFDOUIseUJBQXlCO0FBQUEsTUFDekIsNkJBQTZCO0FBQUEsTUFDN0IsaUJBQWlCO0FBQUEsTUFDakIsZ0JBQWdCO0FBQUEsTUFDaEIsc0JBQXNCO0FBQUEsTUFDdEIsZUFBZTtBQUFBLE1BQ2YseUJBQXlCO0FBQUEsTUFDekIsd0JBQXdCO0FBQUEsTUFDeEIsb0JBQW9CO0FBQUEsTUFDcEIscUJBQXFCO0FBQUEsTUFDckIsaUJBQWlCO0FBQUEsTUFDakIsaUJBQWlCO0FBQUEsTUFDakIsc0JBQXNCO0FBQUEsTUFDdEIsbUNBQW1DO0FBQUEsTUFDbkMscUNBQXFDO0FBQUEsTUFDckMsdUJBQXVCO0FBQUEsTUFDdkIsc0JBQXNCO0FBQUEsTUFDdEIsd0JBQXdCO0FBQUEsTUFDeEIsMkJBQTJCO0FBQUEsTUFDM0IsbUJBQW1CO0FBQUEsTUFDbkIscUJBQXFCO0FBQUEsTUFDckIsc0JBQXNCO0FBQUEsTUFDdEIsc0JBQXNCO0FBQUEsTUFDdEIsOEJBQThCO0FBQUEsTUFDOUIsaUJBQWlCO0FBQUEsTUFDakIseUJBQXlCO0FBQUEsTUFDekIsMkJBQTJCO0FBQUEsTUFDM0IsK0JBQStCO0FBQUEsTUFDL0IsMEJBQTBCO0FBQUEsTUFDMUIsOEJBQThCO0FBQUEsTUFDOUIsaUJBQWlCO0FBQUEsTUFDakIsdUJBQXVCO0FBQUEsTUFDdkIsZ0JBQWdCO0FBQUEsTUFDaEIsMEJBQTBCO0FBQUEsTUFDMUIseUJBQXlCO0FBQUEsTUFDekIsc0JBQXNCO0FBQUEsTUFDdEIsa0JBQWtCO0FBQUEsTUFDbEIsbUJBQW1CO0FBQUEsTUFDbkIsa0JBQWtCO0FBQUEsTUFDbEIsdUJBQXVCO0FBQUEsTUFDdkIsb0NBQW9DO0FBQUEsTUFDcEMsc0NBQXNDO0FBQUEsTUFDdEMsd0JBQXdCO0FBQUEsTUFDeEIsdUJBQXVCO0FBQUEsTUFDdkIseUJBQXlCO0FBQUEsTUFDekIsNEJBQTRCO0FBQUEsTUFDNUIsNEJBQTRCO0FBQUEsTUFDNUIsY0FBYztBQUFBLE1BQ2QsYUFBYTtBQUFBLE1BQ2IsY0FBYztBQUFBLE1BQ2Qsb0JBQW9CO0FBQUEsTUFDcEIsbUJBQW1CO0FBQUEsTUFDbkIsdUJBQXVCO0FBQUEsTUFDdkIsc0JBQXNCO0FBQUEsTUFDdEIscUJBQXFCO0FBQUEsTUFDckIsb0JBQW9CO0FBQUEsTUFDcEIsaUJBQWlCO0FBQUEsTUFDakIsZ0JBQWdCO0FBQUEsTUFDaEIsb0JBQW9CO0FBQUEsTUFDcEIsbUJBQW1CO0FBQUEsTUFDbkIsdUJBQXVCO0FB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LHFCQUFxQjtBQUMxQyxRQUFHLE1BQU87QUFDTixlQUFTLHNCQUFzQjtBQUFBLElBQ25DO0FBQUEsRUFDSixDQUFDO0FBRUQsV0FBUyxVQUFVLElBQUk7QUFDbkIsUUFBSSxXQUFXLFNBQVMsZUFBZSxZQUFZO0FBQy9DLFNBQUc7QUFBQSxJQUNQLE9BQU87QUFDSCxlQUFTLGlCQUFpQixvQkFBb0IsRUFBRTtBQUFBLElBQ3BEO0FBQUEsRUFDSjtBQUVBLFlBQVUsTUFBTTtBQUNaLElBQUksT0FBTztBQUFBLEVBQ2YsQ0FBQzsiLAogICJuYW1lcyI6IFsic2l6ZSIsICJjYWxsIiwgImNhbGwiLCAiY2FsbCIsICJjYWxsIiwgImNhbGwiLCAiSGlkZSIsICJTaG93IiwgInNldFJlc2l6YWJsZSIsICJjYWxsIiwgIndpZHRoIiwgImhlaWdodCIsICJyZXNpemFibGUiLCAiSGlkZSIsICJTaG93IiwgImNhbGwiLCAiZXZlbnROYW1lIiwgIkVycm9yIiwgImNhbGwiLCAiRXJyb3IiLCAiY2FsbCIsICJnZW5lcmF0ZUlEIl0KfQo= +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb24uanMiLCAiLi4vLi4vLi4vcnVudGltZS9ub2RlX21vZHVsZXMvbmFub2lkL25vbi1zZWN1cmUvaW5kZXguanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3J1bnRpbWUuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXIuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZC5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvc3lzdGVtLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jb250ZXh0bWVudS5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3MuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RyYWcuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3NjcmVlbnMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dpbmRvdy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvd21sLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9ldmVudHMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50X3R5cGVzLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9kaWFsb2dzLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxscy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvY29tcGlsZWQvbWFpbi5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBMb2dzIGEgbWVzc2FnZSB0byB0aGUgY29uc29sZSB3aXRoIGN1c3RvbSBmb3JtYXR0aW5nLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVidWdMb2cobWVzc2FnZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAnJWMgd2FpbHMzICVjICcgKyBtZXNzYWdlICsgJyAnLFxuICAgICAgICAnYmFja2dyb3VuZDogI2FhMDAwMDsgY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDNweCAwcHggMHB4IDNweDsgcGFkZGluZzogMXB4OyBmb250LXNpemU6IDAuN3JlbScsXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjMDA5OTAwOyBjb2xvcjogI2ZmZjsgYm9yZGVyLXJhZGl1czogMHB4IDNweCAzcHggMHB4OyBwYWRkaW5nOiAxcHg7IGZvbnQtc2l6ZTogMC43cmVtJ1xuICAgICk7XG59IiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZVwiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQXBwbGljYXRpb24sICcnKTtcblxuY29uc3QgSGlkZU1ldGhvZCA9IDA7XG5jb25zdCBTaG93TWV0aG9kID0gMTtcbmNvbnN0IFF1aXRNZXRob2QgPSAyO1xuXG4vKipcbiAqIEhpZGVzIGEgY2VydGFpbiBtZXRob2QgYnkgY2FsbGluZyB0aGUgSGlkZU1ldGhvZCBmdW5jdGlvbi5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XG4gICAgcmV0dXJuIGNhbGwoSGlkZU1ldGhvZCk7XG59XG5cbi8qKlxuICogQ2FsbHMgdGhlIFNob3dNZXRob2QgYW5kIHJldHVybnMgdGhlIHJlc3VsdC5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpIHtcbiAgICByZXR1cm4gY2FsbChTaG93TWV0aG9kKTtcbn1cblxuLyoqXG4gKiBDYWxscyB0aGUgUXVpdE1ldGhvZCB0byB0ZXJtaW5hdGUgdGhlIHByb2dyYW0uXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFF1aXQoKSB7XG4gICAgcmV0dXJuIGNhbGwoUXVpdE1ldGhvZCk7XG59XG4iLCAibGV0IHVybEFscGhhYmV0ID1cbiAgJ3VzZWFuZG9tLTI2VDE5ODM0MFBYNzVweEpBQ0tWRVJZTUlOREJVU0hXT0xGX0dRWmJmZ2hqa2xxdnd5enJpY3QnXG5leHBvcnQgbGV0IGN1c3RvbUFscGhhYmV0ID0gKGFscGhhYmV0LCBkZWZhdWx0U2l6ZSA9IDIxKSA9PiB7XG4gIHJldHVybiAoc2l6ZSA9IGRlZmF1bHRTaXplKSA9PiB7XG4gICAgbGV0IGlkID0gJydcbiAgICBsZXQgaSA9IHNpemVcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICBpZCArPSBhbHBoYWJldFsoTWF0aC5yYW5kb20oKSAqIGFscGhhYmV0Lmxlbmd0aCkgfCAwXVxuICAgIH1cbiAgICByZXR1cm4gaWRcbiAgfVxufVxuZXhwb3J0IGxldCBuYW5vaWQgPSAoc2l6ZSA9IDIxKSA9PiB7XG4gIGxldCBpZCA9ICcnXG4gIGxldCBpID0gc2l6ZVxuICB3aGlsZSAoaS0tKSB7XG4gICAgaWQgKz0gdXJsQWxwaGFiZXRbKE1hdGgucmFuZG9tKCkgKiA2NCkgfCAwXVxuICB9XG4gIHJldHVybiBpZFxufVxuIiwgIi8qXG4gXyAgICAgX18gICAgIF8gX19cbnwgfCAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQgeyBuYW5vaWQgfSBmcm9tICduYW5vaWQvbm9uLXNlY3VyZSc7XG5cbmNvbnN0IHJ1bnRpbWVVUkwgPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luICsgXCIvd2FpbHMvcnVudGltZVwiO1xuXG4vLyBPYmplY3QgTmFtZXNcbmV4cG9ydCBjb25zdCBvYmplY3ROYW1lcyA9IHtcbiAgICBDYWxsOiAwLFxuICAgIENsaXBib2FyZDogMSxcbiAgICBBcHBsaWNhdGlvbjogMixcbiAgICBFdmVudHM6IDMsXG4gICAgQ29udGV4dE1lbnU6IDQsXG4gICAgRGlhbG9nOiA1LFxuICAgIFdpbmRvdzogNixcbiAgICBTY3JlZW5zOiA3LFxuICAgIFN5c3RlbTogOCxcbiAgICBCcm93c2VyOiA5LFxufVxuZXhwb3J0IGxldCBjbGllbnRJZCA9IG5hbm9pZCgpO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBydW50aW1lIGNhbGxlciBmdW5jdGlvbiB0aGF0IGludm9rZXMgYSBzcGVjaWZpZWQgbWV0aG9kIG9uIGEgZ2l2ZW4gb2JqZWN0IHdpdGhpbiBhIHNwZWNpZmllZCB3aW5kb3cgY29udGV4dC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IC0gVGhlIG9iamVjdCBvbiB3aGljaCB0aGUgbWV0aG9kIGlzIHRvIGJlIGludm9rZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgY29udGV4dCBpbiB3aGljaCB0aGUgbWV0aG9kIHNob3VsZCBiZSBjYWxsZWQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IEEgcnVudGltZSBjYWxsZXIgZnVuY3Rpb24gdGhhdCB0YWtlcyB0aGUgbWV0aG9kIG5hbWUgYW5kIG9wdGlvbmFsbHkgYXJndW1lbnRzIGFuZCBpbnZva2VzIHRoZSBtZXRob2Qgd2l0aGluIHRoZSBzcGVjaWZpZWQgd2luZG93IGNvbnRleHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdCwgd2luZG93TmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAobWV0aG9kLCBhcmdzPW51bGwpIHtcbiAgICAgICAgcmV0dXJuIHJ1bnRpbWVDYWxsKG9iamVjdCArIFwiLlwiICsgbWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKTtcbiAgICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcnVudGltZSBjYWxsZXIgd2l0aCBzcGVjaWZpZWQgSUQuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3QgdG8gaW52b2tlIHRoZSBtZXRob2Qgb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cuXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gLSBUaGUgbmV3IHJ1bnRpbWUgY2FsbGVyIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3QsIHdpbmRvd05hbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG1ldGhvZCwgYXJncz1udWxsKSB7XG4gICAgICAgIHJldHVybiBydW50aW1lQ2FsbFdpdGhJRChvYmplY3QsIG1ldGhvZCwgd2luZG93TmFtZSwgYXJncyk7XG4gICAgfTtcbn1cblxuXG5mdW5jdGlvbiBydW50aW1lQ2FsbChtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcbiAgICBpZiggbWV0aG9kICkge1xuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcIm1ldGhvZFwiLCBtZXRob2QpO1xuICAgIH1cbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICB9O1xuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuICAgIGlmIChhcmdzKSB7XG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiYXJnc1wiLCBKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgfVxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGZldGNoKHVybCwgZmV0Y2hPcHRpb25zKVxuICAgICAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayBjb250ZW50IHR5cGVcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpICYmIHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpLmluZGV4T2YoXCJhcHBsaWNhdGlvbi9qc29uXCIpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKHJlc3BvbnNlLnN0YXR1c1RleHQpKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbihkYXRhID0+IHJlc29sdmUoZGF0YSkpXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHJ1bnRpbWVDYWxsV2l0aElEKG9iamVjdElELCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcbiAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcIm9iamVjdFwiLCBvYmplY3RJRCk7XG4gICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJtZXRob2RcIiwgbWV0aG9kKTtcbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICB9O1xuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuICAgIGlmIChhcmdzKSB7XG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiYXJnc1wiLCBKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgfVxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBmZXRjaCh1cmwsIGZldGNoT3B0aW9ucylcbiAgICAgICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgY29udGVudCB0eXBlXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKSAmJiByZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKS5pbmRleE9mKFwiYXBwbGljYXRpb24vanNvblwiKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcihyZXNwb25zZS5zdGF0dXNUZXh0KSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oZGF0YSA9PiByZXNvbHZlKGRhdGEpKVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgIH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkJyb3dzZXIsICcnKTtcbmNvbnN0IEJyb3dzZXJPcGVuVVJMID0gMDtcblxuLyoqXG4gKiBPcGVuIGEgYnJvd3NlciB3aW5kb3cgdG8gdGhlIGdpdmVuIFVSTFxuICogQHBhcmFtIHtzdHJpbmd9IHVybCAtIFRoZSBVUkwgdG8gb3BlblxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9wZW5VUkwodXJsKSB7XG4gICAgcmV0dXJuIGNhbGwoQnJvd3Nlck9wZW5VUkwsIHt1cmx9KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkNsaXBib2FyZCwgJycpO1xuY29uc3QgQ2xpcGJvYXJkU2V0VGV4dCA9IDA7XG5jb25zdCBDbGlwYm9hcmRUZXh0ID0gMTtcblxuLyoqXG4gKiBTZXRzIHRoZSB0ZXh0IHRvIHRoZSBDbGlwYm9hcmQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgdGV4dCB0byBiZSBzZXQgdG8gdGhlIENsaXBib2FyZC5cbiAqIEByZXR1cm4ge1Byb21pc2V9IC0gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIHN1Y2Nlc3NmdWwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRUZXh0KHRleHQpIHtcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRTZXRUZXh0LCB7dGV4dH0pO1xufVxuXG4vKipcbiAqIEdldCB0aGUgQ2xpcGJvYXJkIHRleHRcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHRleHQgZnJvbSB0aGUgQ2xpcGJvYXJkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gVGV4dCgpIHtcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRUZXh0KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5sZXQgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU3lzdGVtLCAnJyk7XG5jb25zdCBzeXN0ZW1Jc0RhcmtNb2RlID0gMDtcbmNvbnN0IGVudmlyb25tZW50ID0gMTtcblxuZXhwb3J0IGZ1bmN0aW9uIGludm9rZShtc2cpIHtcbiAgICBpZih3aW5kb3cuY2hyb21lKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuY2hyb21lLndlYnZpZXcucG9zdE1lc3NhZ2UobXNnKTtcbiAgICB9XG4gICAgcmV0dXJuIHdpbmRvdy53ZWJraXQubWVzc2FnZUhhbmRsZXJzLmV4dGVybmFsLnBvc3RNZXNzYWdlKG1zZyk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBSZXRyaWV2ZXMgdGhlIHN5c3RlbSBkYXJrIG1vZGUgc3RhdHVzLlxuICogQHJldHVybnMge1Byb21pc2U8Ym9vbGVhbj59IC0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBib29sZWFuIHZhbHVlIGluZGljYXRpbmcgaWYgdGhlIHN5c3RlbSBpcyBpbiBkYXJrIG1vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0RhcmtNb2RlKCkge1xuICAgIHJldHVybiBjYWxsKHN5c3RlbUlzRGFya01vZGUpO1xufVxuXG4vKipcbiAqIEZldGNoZXMgdGhlIGNhcGFiaWxpdGllcyBvZiB0aGUgYXBwbGljYXRpb24gZnJvbSB0aGUgc2VydmVyLlxuICpcbiAqIEBhc3luY1xuICogQGZ1bmN0aW9uIENhcGFiaWxpdGllc1xuICogQHJldHVybnMge1Byb21pc2U8T2JqZWN0Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGNhcGFiaWxpdGllcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhcGFiaWxpdGllcygpIHtcbiAgICBsZXQgcmVzcG9uc2UgPSBmZXRjaChcIi93YWlscy9jYXBhYmlsaXRpZXNcIik7XG4gICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbn1cblxuLyoqXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBFbnZpcm9ubWVudEluZm9cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBPUyAtIFRoZSBvcGVyYXRpbmcgc3lzdGVtIGluIHVzZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBBcmNoIC0gVGhlIGFyY2hpdGVjdHVyZSBvZiB0aGUgc3lzdGVtLlxuICovXG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBSZXRyaWV2ZXMgZW52aXJvbm1lbnQgZGV0YWlscy5cbiAqIEByZXR1cm5zIHtQcm9taXNlPEVudmlyb25tZW50SW5mbz59IC0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgT1MgYW5kIHN5c3RlbSBhcmNoaXRlY3R1cmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFbnZpcm9ubWVudCgpIHtcbiAgICByZXR1cm4gY2FsbChlbnZpcm9ubWVudCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cy5cbiAqXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBvcGVyYXRpbmcgc3lzdGVtIGlzIFdpbmRvd3MsIG90aGVyd2lzZSBmYWxzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzV2luZG93cygpIHtcbiAgICByZXR1cm4gd2luZG93Ll93YWlscy5lbnZpcm9ubWVudC5PUyA9PT0gXCJ3aW5kb3dzXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgTGludXguXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIExpbnV4LCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0xpbnV4KCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcImxpbnV4XCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGlzIGEgbWFjT1Mgb3BlcmF0aW5nIHN5c3RlbS5cbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgZW52aXJvbm1lbnQgaXMgbWFjT1MsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzTWFjKCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcImRhcndpblwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQU1ENjQoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuQXJjaCA9PT0gXCJhbWQ2NFwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBhcmNoaXRlY3R1cmUgaXMgQVJNLlxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBjdXJyZW50IGFyY2hpdGVjdHVyZSBpcyBBUk0sIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQVJNKCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZS5cbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBSZXR1cm5zIHRydWUgaWYgdGhlIGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZSwgb3RoZXJ3aXNlIHJldHVybnMgZmFsc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0FSTTY0KCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtNjRcIjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIElzRGVidWcoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuRGVidWcgPT09IHRydWU7XG59XG5cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5pbXBvcnQge0lzRGVidWd9IGZyb20gXCIuL3N5c3RlbVwiO1xuXG4vLyBzZXR1cFxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgY29udGV4dE1lbnVIYW5kbGVyKTtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ29udGV4dE1lbnUsICcnKTtcbmNvbnN0IENvbnRleHRNZW51T3BlbiA9IDA7XG5cbmZ1bmN0aW9uIG9wZW5Db250ZXh0TWVudShpZCwgeCwgeSwgZGF0YSkge1xuICAgIHZvaWQgY2FsbChDb250ZXh0TWVudU9wZW4sIHtpZCwgeCwgeSwgZGF0YX0pO1xufVxuXG5mdW5jdGlvbiBjb250ZXh0TWVudUhhbmRsZXIoZXZlbnQpIHtcbiAgICAvLyBDaGVjayBmb3IgY3VzdG9tIGNvbnRleHQgbWVudVxuICAgIGxldCBlbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgIGxldCBjdXN0b21Db250ZXh0TWVudSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoXCItLWN1c3RvbS1jb250ZXh0bWVudVwiKTtcbiAgICBjdXN0b21Db250ZXh0TWVudSA9IGN1c3RvbUNvbnRleHRNZW51ID8gY3VzdG9tQ29udGV4dE1lbnUudHJpbSgpIDogXCJcIjtcbiAgICBpZiAoY3VzdG9tQ29udGV4dE1lbnUpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgbGV0IGN1c3RvbUNvbnRleHRNZW51RGF0YSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoXCItLWN1c3RvbS1jb250ZXh0bWVudS1kYXRhXCIpO1xuICAgICAgICBvcGVuQ29udGV4dE1lbnUoY3VzdG9tQ29udGV4dE1lbnUsIGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFksIGN1c3RvbUNvbnRleHRNZW51RGF0YSk7XG4gICAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpO1xufVxuXG5cbi8qXG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IGF1dG87IChkZWZhdWx0KSB3aWxsIHNob3cgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51IGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlIE9SIHRleHQgaGFzIGJlZW4gc2VsZWN0ZWQgT1IgZWxlbWVudCBpcyBpbnB1dCBvciB0ZXh0YXJlYVxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBzaG93OyB3aWxsIGFsd2F5cyBzaG93IHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBoaWRlOyB3aWxsIGFsd2F5cyBoaWRlIHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuXG5UaGlzIHJ1bGUgaXMgaW5oZXJpdGVkIGxpa2Ugbm9ybWFsIENTUyBydWxlcywgc28gbmVzdGluZyB3b3JrcyBhcyBleHBlY3RlZFxuKi9cbmZ1bmN0aW9uIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpIHtcblxuICAgIC8vIERlYnVnIGJ1aWxkcyBhbHdheXMgc2hvdyB0aGUgbWVudVxuICAgIGlmIChJc0RlYnVnKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFByb2Nlc3MgZGVmYXVsdCBjb250ZXh0IG1lbnVcbiAgICBjb25zdCBlbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgIGNvbnN0IGNvbXB1dGVkU3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KTtcbiAgICBjb25zdCBkZWZhdWx0Q29udGV4dE1lbnVBY3Rpb24gPSBjb21wdXRlZFN0eWxlLmdldFByb3BlcnR5VmFsdWUoXCItLWRlZmF1bHQtY29udGV4dG1lbnVcIikudHJpbSgpO1xuICAgIHN3aXRjaCAoZGVmYXVsdENvbnRleHRNZW51QWN0aW9uKSB7XG4gICAgICAgIGNhc2UgXCJzaG93XCI6XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNhc2UgXCJoaWRlXCI6XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgY29udGVudEVkaXRhYmxlIGlzIHRydWVcbiAgICAgICAgICAgIGlmIChlbGVtZW50LmlzQ29udGVudEVkaXRhYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0ZXh0IGhhcyBiZWVuIHNlbGVjdGVkXG4gICAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICAgICAgICBjb25zdCBoYXNTZWxlY3Rpb24gPSAoc2VsZWN0aW9uLnRvU3RyaW5nKCkubGVuZ3RoID4gMClcbiAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGVjdGlvbi5yYW5nZUNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdChpKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVjdHMgPSByYW5nZS5nZXRDbGllbnRSZWN0cygpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHJlY3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0ID0gcmVjdHNbal07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludChyZWN0LmxlZnQsIHJlY3QudG9wKSA9PT0gZWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRhZ25hbWUgaXMgaW5wdXQgb3IgdGV4dGFyZWFcbiAgICAgICAgICAgIGlmIChlbGVtZW50LnRhZ05hbWUgPT09IFwiSU5QVVRcIiB8fCBlbGVtZW50LnRhZ05hbWUgPT09IFwiVEVYVEFSRUFcIikge1xuICAgICAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24gfHwgKCFlbGVtZW50LnJlYWRPbmx5ICYmICFlbGVtZW50LmRpc2FibGVkKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBoaWRlIGRlZmF1bHQgY29udGV4dCBtZW51XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIFJldHJpZXZlcyB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBzcGVjaWZpZWQga2V5IGZyb20gdGhlIGZsYWcgbWFwLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXlTdHJpbmcgLSBUaGUga2V5IHRvIHJldHJpZXZlIHRoZSB2YWx1ZSBmb3IuXG4gKiBAcmV0dXJuIHsqfSAtIFRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBrZXkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRGbGFnKGtleVN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmZsYWdzW2tleVN0cmluZ107XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gcmV0cmlldmUgZmxhZyAnXCIgKyBrZXlTdHJpbmcgKyBcIic6IFwiICsgZSk7XG4gICAgfVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7aW52b2tlLCBJc1dpbmRvd3N9IGZyb20gXCIuL3N5c3RlbVwiO1xuaW1wb3J0IHtHZXRGbGFnfSBmcm9tIFwiLi9mbGFnc1wiO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLnNldFJlc2l6YWJsZSA9IHNldFJlc2l6YWJsZTtcbndpbmRvdy5fd2FpbHMuZW5kRHJhZyA9IGVuZERyYWc7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgb25Nb3VzZURvd24pO1xud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG9uTW91c2VNb3ZlKTtcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25Nb3VzZVVwKTtcblxuXG5sZXQgc2hvdWxkRHJhZyA9IGZhbHNlO1xubGV0IHJlc2l6ZUVkZ2UgPSBudWxsO1xubGV0IHJlc2l6YWJsZSA9IGZhbHNlO1xubGV0IGRlZmF1bHRDdXJzb3IgPSBcImF1dG9cIjtcblxuZnVuY3Rpb24gZHJhZ1Rlc3QoZSkge1xuICAgIGxldCB2YWwgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlLnRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZShcIi0td2Via2l0LWFwcC1yZWdpb25cIik7XG4gICAgaWYgKCF2YWwgfHwgdmFsID09PSBcIlwiIHx8IHZhbC50cmltKCkgIT09IFwiZHJhZ1wiIHx8IGUuYnV0dG9ucyAhPT0gMSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBlLmRldGFpbCA9PT0gMTtcbn1cblxuZnVuY3Rpb24gc2V0UmVzaXphYmxlKHZhbHVlKSB7XG4gICAgcmVzaXphYmxlID0gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIGVuZERyYWcoKSB7XG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5jdXJzb3IgPSAnZGVmYXVsdCc7XG4gICAgc2hvdWxkRHJhZyA9IGZhbHNlO1xufVxuXG5mdW5jdGlvbiB0ZXN0UmVzaXplKCkge1xuICAgIGlmKCByZXNpemVFZGdlICkge1xuICAgICAgICBpbnZva2UoYHJlc2l6ZToke3Jlc2l6ZUVkZ2V9YCk7XG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gb25Nb3VzZURvd24oZSkge1xuICAgIGlmKElzV2luZG93cygpICYmIHRlc3RSZXNpemUoKSB8fCBkcmFnVGVzdChlKSkge1xuICAgICAgICBzaG91bGREcmFnID0gISFpc1ZhbGlkRHJhZyhlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzVmFsaWREcmFnKGUpIHtcbiAgICAvLyBJZ25vcmUgZHJhZyBvbiBzY3JvbGxiYXJzXG4gICAgcmV0dXJuICEoZS5vZmZzZXRYID4gZS50YXJnZXQuY2xpZW50V2lkdGggfHwgZS5vZmZzZXRZID4gZS50YXJnZXQuY2xpZW50SGVpZ2h0KTtcbn1cblxuZnVuY3Rpb24gb25Nb3VzZVVwKGUpIHtcbiAgICBsZXQgbW91c2VQcmVzc2VkID0gZS5idXR0b25zICE9PSB1bmRlZmluZWQgPyBlLmJ1dHRvbnMgOiBlLndoaWNoO1xuICAgIGlmIChtb3VzZVByZXNzZWQgPiAwKSB7XG4gICAgICAgIGVuZERyYWcoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldFJlc2l6ZShjdXJzb3IgPSBkZWZhdWx0Q3Vyc29yKSB7XG4gICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmN1cnNvciA9IGN1cnNvcjtcbiAgICByZXNpemVFZGdlID0gY3Vyc29yO1xufVxuXG5mdW5jdGlvbiBvbk1vdXNlTW92ZShlKSB7XG4gICAgc2hvdWxkRHJhZyA9IGNoZWNrRHJhZyhlKTtcbiAgICBpZiAoSXNXaW5kb3dzKCkgJiYgcmVzaXphYmxlKSB7XG4gICAgICAgIGhhbmRsZVJlc2l6ZShlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrRHJhZyhlKSB7XG4gICAgbGV0IG1vdXNlUHJlc3NlZCA9IGUuYnV0dG9ucyAhPT0gdW5kZWZpbmVkID8gZS5idXR0b25zIDogZS53aGljaDtcbiAgICBpZihzaG91bGREcmFnICYmIG1vdXNlUHJlc3NlZCA+IDApIHtcbiAgICAgICAgaW52b2tlKFwiZHJhZ1wiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gc2hvdWxkRHJhZztcbn1cblxuZnVuY3Rpb24gaGFuZGxlUmVzaXplKGUpIHtcbiAgICBsZXQgcmVzaXplSGFuZGxlSGVpZ2h0ID0gR2V0RmxhZyhcInN5c3RlbS5yZXNpemVIYW5kbGVIZWlnaHRcIikgfHwgNTtcbiAgICBsZXQgcmVzaXplSGFuZGxlV2lkdGggPSBHZXRGbGFnKFwic3lzdGVtLnJlc2l6ZUhhbmRsZVdpZHRoXCIpIHx8IDU7XG5cbiAgICAvLyBFeHRyYSBwaXhlbHMgZm9yIHRoZSBjb3JuZXIgYXJlYXNcbiAgICBsZXQgY29ybmVyRXh0cmEgPSBHZXRGbGFnKFwicmVzaXplQ29ybmVyRXh0cmFcIikgfHwgMTA7XG5cbiAgICBsZXQgcmlnaHRCb3JkZXIgPSB3aW5kb3cub3V0ZXJXaWR0aCAtIGUuY2xpZW50WCA8IHJlc2l6ZUhhbmRsZVdpZHRoO1xuICAgIGxldCBsZWZ0Qm9yZGVyID0gZS5jbGllbnRYIDwgcmVzaXplSGFuZGxlV2lkdGg7XG4gICAgbGV0IHRvcEJvcmRlciA9IGUuY2xpZW50WSA8IHJlc2l6ZUhhbmRsZUhlaWdodDtcbiAgICBsZXQgYm90dG9tQm9yZGVyID0gd2luZG93Lm91dGVySGVpZ2h0IC0gZS5jbGllbnRZIDwgcmVzaXplSGFuZGxlSGVpZ2h0O1xuXG4gICAgLy8gQWRqdXN0IGZvciBjb3JuZXJzXG4gICAgbGV0IHJpZ2h0Q29ybmVyID0gd2luZG93Lm91dGVyV2lkdGggLSBlLmNsaWVudFggPCAocmVzaXplSGFuZGxlV2lkdGggKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IGxlZnRDb3JuZXIgPSBlLmNsaWVudFggPCAocmVzaXplSGFuZGxlV2lkdGggKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IHRvcENvcm5lciA9IGUuY2xpZW50WSA8IChyZXNpemVIYW5kbGVIZWlnaHQgKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IGJvdHRvbUNvcm5lciA9IHdpbmRvdy5vdXRlckhlaWdodCAtIGUuY2xpZW50WSA8IChyZXNpemVIYW5kbGVIZWlnaHQgKyBjb3JuZXJFeHRyYSk7XG5cbiAgICAvLyBJZiB3ZSBhcmVuJ3Qgb24gYW4gZWRnZSwgYnV0IHdlcmUsIHJlc2V0IHRoZSBjdXJzb3IgdG8gZGVmYXVsdFxuICAgIGlmICghbGVmdEJvcmRlciAmJiAhcmlnaHRCb3JkZXIgJiYgIXRvcEJvcmRlciAmJiAhYm90dG9tQm9yZGVyICYmIHJlc2l6ZUVkZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzZXRSZXNpemUoKTtcbiAgICB9XG4gICAgLy8gQWRqdXN0ZWQgZm9yIGNvcm5lciBhcmVhc1xuICAgIGVsc2UgaWYgKHJpZ2h0Q29ybmVyICYmIGJvdHRvbUNvcm5lcikgc2V0UmVzaXplKFwic2UtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRDb3JuZXIgJiYgYm90dG9tQ29ybmVyKSBzZXRSZXNpemUoXCJzdy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAobGVmdENvcm5lciAmJiB0b3BDb3JuZXIpIHNldFJlc2l6ZShcIm53LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BDb3JuZXIgJiYgcmlnaHRDb3JuZXIpIHNldFJlc2l6ZShcIm5lLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Qm9yZGVyKSBzZXRSZXNpemUoXCJ3LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BCb3JkZXIpIHNldFJlc2l6ZShcIm4tcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwicy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAocmlnaHRCb3JkZXIpIHNldFJlc2l6ZShcImUtcmVzaXplXCIpO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUG9zaXRpb25cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIFggY29vcmRpbmF0ZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBZIC0gVGhlIFkgY29vcmRpbmF0ZS5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNpemVcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIHdpZHRoLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFkgLSBUaGUgaGVpZ2h0LlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBSZWN0XG4gKiBAcHJvcGVydHkge251bWJlcn0gWCAtIFRoZSBYIGNvb3JkaW5hdGUgb2YgdGhlIHRvcC1sZWZ0IGNvcm5lci5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBZIC0gVGhlIFkgY29vcmRpbmF0ZSBvZiB0aGUgdG9wLWxlZnQgY29ybmVyLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSByZWN0YW5nbGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gSGVpZ2h0IC0gVGhlIGhlaWdodCBvZiB0aGUgcmVjdGFuZ2xlLlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7KCdaZXJvJ3wnTmluZXR5J3wnT25lRWlnaHR5J3wnVHdvU2V2ZW50eScpfSBSb3RhdGlvblxuICogVGhlIHJvdGF0aW9uIG9mIHRoZSBzY3JlZW4uIENhbiBiZSBvbmUgb2YgJ1plcm8nLCAnTmluZXR5JywgJ09uZUVpZ2h0eScsICdUd29TZXZlbnR5Jy5cbiAqL1xuXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gU2NyZWVuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSWQgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHNjcmVlbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBOYW1lIC0gSHVtYW4gcmVhZGFibGUgbmFtZSBvZiB0aGUgc2NyZWVuLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFNjYWxlIC0gVGhlIHJlc29sdXRpb24gc2NhbGUgb2YgdGhlIHNjcmVlbi4gMSA9IHN0YW5kYXJkIHJlc29sdXRpb24sIDIgPSBoaWdoIChSZXRpbmEpLCBldGMuXG4gKiBAcHJvcGVydHkge1Bvc2l0aW9ufSBQb3NpdGlvbiAtIENvbnRhaW5zIHRoZSBYIGFuZCBZIGNvb3JkaW5hdGVzIG9mIHRoZSBzY3JlZW4ncyBwb3NpdGlvbi5cbiAqIEBwcm9wZXJ0eSB7U2l6ZX0gU2l6ZSAtIENvbnRhaW5zIHRoZSB3aWR0aCBhbmQgaGVpZ2h0IG9mIHRoZSBzY3JlZW4uXG4gKiBAcHJvcGVydHkge1JlY3R9IEJvdW5kcyAtIENvbnRhaW5zIHRoZSBib3VuZHMgb2YgdGhlIHNjcmVlbiBpbiB0ZXJtcyBvZiBYLCBZLCBXaWR0aCwgYW5kIEhlaWdodC5cbiAqIEBwcm9wZXJ0eSB7UmVjdH0gV29ya0FyZWEgLSBDb250YWlucyB0aGUgYXJlYSBvZiB0aGUgc2NyZWVuIHRoYXQgaXMgYWN0dWFsbHkgdXNhYmxlIChleGNsdWRpbmcgdGFza2JhciBhbmQgb3RoZXIgc3lzdGVtIFVJKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gSXNQcmltYXJ5IC0gVHJ1ZSBpZiB0aGlzIGlzIHRoZSBwcmltYXJ5IG1vbml0b3Igc2VsZWN0ZWQgYnkgdGhlIHVzZXIgaW4gdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gKiBAcHJvcGVydHkge1JvdGF0aW9ufSBSb3RhdGlvbiAtIFRoZSByb3RhdGlvbiBvZiB0aGUgc2NyZWVuLlxuICovXG5cblxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU2NyZWVucywgJycpO1xuXG5jb25zdCBnZXRBbGwgPSAwO1xuY29uc3QgZ2V0UHJpbWFyeSA9IDE7XG5jb25zdCBnZXRDdXJyZW50ID0gMjtcblxuLyoqXG4gKiBHZXRzIGFsbCBzY3JlZW5zLlxuICogQHJldHVybnMge1Byb21pc2U8U2NyZWVuW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiBTY3JlZW4gb2JqZWN0cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldEFsbCgpIHtcbiAgICByZXR1cm4gY2FsbChnZXRBbGwpO1xufVxuLyoqXG4gKiBHZXRzIHRoZSBwcmltYXJ5IHNjcmVlbi5cbiAqIEByZXR1cm5zIHtQcm9taXNlPFNjcmVlbj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBwcmltYXJ5IHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldFByaW1hcnkoKSB7XG4gICAgcmV0dXJuIGNhbGwoZ2V0UHJpbWFyeSk7XG59XG4vKipcbiAqIEdldHMgdGhlIGN1cnJlbnQgYWN0aXZlIHNjcmVlbi5cbiAqXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxTY3JlZW4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjdXJyZW50IGFjdGl2ZSBzY3JlZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRDdXJyZW50KCkge1xuICAgIHJldHVybiBjYWxsKGdldEN1cnJlbnQpO1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vLyBJbXBvcnQgc2NyZWVuIGpzZG9jIGRlZmluaXRpb24gZnJvbSAuL3NjcmVlbnMuanNcbi8qKlxuICogQHR5cGVkZWYge2ltcG9ydChcIi4vc2NyZWVuc1wiKS5TY3JlZW59IFNjcmVlblxuICovXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcblxuY29uc3QgY2VudGVyID0gMDtcbmNvbnN0IHNldFRpdGxlID0gMTtcbmNvbnN0IGZ1bGxzY3JlZW4gPSAyO1xuY29uc3QgdW5GdWxsc2NyZWVuID0gMztcbmNvbnN0IHNldFNpemUgPSA0O1xuY29uc3Qgc2l6ZSA9IDU7XG5jb25zdCBzZXRNYXhTaXplID0gNjtcbmNvbnN0IHNldE1pblNpemUgPSA3O1xuY29uc3Qgc2V0QWx3YXlzT25Ub3AgPSA4O1xuY29uc3Qgc2V0UmVsYXRpdmVQb3NpdGlvbiA9IDk7XG5jb25zdCByZWxhdGl2ZVBvc2l0aW9uID0gMTA7XG5jb25zdCBzY3JlZW4gPSAxMTtcbmNvbnN0IGhpZGUgPSAxMjtcbmNvbnN0IG1heGltaXNlID0gMTM7XG5jb25zdCB1bk1heGltaXNlID0gMTQ7XG5jb25zdCB0b2dnbGVNYXhpbWlzZSA9IDE1O1xuY29uc3QgbWluaW1pc2UgPSAxNjtcbmNvbnN0IHVuTWluaW1pc2UgPSAxNztcbmNvbnN0IHJlc3RvcmUgPSAxODtcbmNvbnN0IHNob3cgPSAxOTtcbmNvbnN0IGNsb3NlID0gMjA7XG5jb25zdCBzZXRCYWNrZ3JvdW5kQ29sb3VyID0gMjE7XG5jb25zdCBzZXRSZXNpemFibGUgPSAyMjtcbmNvbnN0IHdpZHRoID0gMjM7XG5jb25zdCBoZWlnaHQgPSAyNDtcbmNvbnN0IHpvb21JbiA9IDI1O1xuY29uc3Qgem9vbU91dCA9IDI2O1xuY29uc3Qgem9vbVJlc2V0ID0gMjc7XG5jb25zdCBnZXRab29tTGV2ZWwgPSAyODtcbmNvbnN0IHNldFpvb21MZXZlbCA9IDI5O1xuXG5jb25zdCB0aGlzV2luZG93ID0gR2V0KCcnKTtcblxuZnVuY3Rpb24gY3JlYXRlV2luZG93KGNhbGwpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBHZXQ6ICh3aW5kb3dOYW1lKSA9PiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKSxcbiAgICAgICAgQ2VudGVyOiAoKSA9PiBjYWxsKGNlbnRlciksXG4gICAgICAgIFNldFRpdGxlOiAodGl0bGUpID0+IGNhbGwoc2V0VGl0bGUsIHt0aXRsZX0pLFxuICAgICAgICBGdWxsc2NyZWVuOiAoKSA9PiBjYWxsKGZ1bGxzY3JlZW4pLFxuICAgICAgICBVbkZ1bGxzY3JlZW46ICgpID0+IGNhbGwodW5GdWxsc2NyZWVuKSxcbiAgICAgICAgU2V0U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2l6ZTogKCkgPT4gY2FsbChzaXplKSxcbiAgICAgICAgU2V0TWF4U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWF4U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2V0TWluU2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWluU2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2V0QWx3YXlzT25Ub3A6IChvblRvcCkgPT4gY2FsbChzZXRBbHdheXNPblRvcCwge2Fsd2F5c09uVG9wOiBvblRvcH0pLFxuICAgICAgICBTZXRSZWxhdGl2ZVBvc2l0aW9uOiAoeCwgeSkgPT4gY2FsbChzZXRSZWxhdGl2ZVBvc2l0aW9uLCB7eCwgeX0pLFxuICAgICAgICBSZWxhdGl2ZVBvc2l0aW9uOiAoKSA9PiBjYWxsKHJlbGF0aXZlUG9zaXRpb24pLFxuICAgICAgICBTY3JlZW46ICgpID0+IGNhbGwoc2NyZWVuKSxcbiAgICAgICAgSGlkZTogKCkgPT4gY2FsbChoaWRlKSxcbiAgICAgICAgTWF4aW1pc2U6ICgpID0+IGNhbGwobWF4aW1pc2UpLFxuICAgICAgICBVbk1heGltaXNlOiAoKSA9PiBjYWxsKHVuTWF4aW1pc2UpLFxuICAgICAgICBUb2dnbGVNYXhpbWlzZTogKCkgPT4gY2FsbCh0b2dnbGVNYXhpbWlzZSksXG4gICAgICAgIE1pbmltaXNlOiAoKSA9PiBjYWxsKG1pbmltaXNlKSxcbiAgICAgICAgVW5NaW5pbWlzZTogKCkgPT4gY2FsbCh1bk1pbmltaXNlKSxcbiAgICAgICAgUmVzdG9yZTogKCkgPT4gY2FsbChyZXN0b3JlKSxcbiAgICAgICAgU2hvdzogKCkgPT4gY2FsbChzaG93KSxcbiAgICAgICAgQ2xvc2U6ICgpID0+IGNhbGwoY2xvc2UpLFxuICAgICAgICBTZXRCYWNrZ3JvdW5kQ29sb3VyOiAociwgZywgYiwgYSkgPT4gY2FsbChzZXRCYWNrZ3JvdW5kQ29sb3VyLCB7ciwgZywgYiwgYX0pLFxuICAgICAgICBTZXRSZXNpemFibGU6IChyZXNpemFibGUpID0+IGNhbGwoc2V0UmVzaXphYmxlLCB7cmVzaXphYmxlfSksXG4gICAgICAgIFdpZHRoOiAoKSA9PiBjYWxsKHdpZHRoKSxcbiAgICAgICAgSGVpZ2h0OiAoKSA9PiBjYWxsKGhlaWdodCksXG4gICAgICAgIFpvb21JbjogKCkgPT4gY2FsbCh6b29tSW4pLFxuICAgICAgICBab29tT3V0OiAoKSA9PiBjYWxsKHpvb21PdXQpLFxuICAgICAgICBab29tUmVzZXQ6ICgpID0+IGNhbGwoem9vbVJlc2V0KSxcbiAgICAgICAgR2V0Wm9vbUxldmVsOiAoKSA9PiBjYWxsKGdldFpvb21MZXZlbCksXG4gICAgICAgIFNldFpvb21MZXZlbDogKHpvb21MZXZlbCkgPT4gY2FsbChzZXRab29tTGV2ZWwsIHt6b29tTGV2ZWx9KSxcbiAgICB9O1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNwZWNpZmllZCB3aW5kb3cuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHdpbmRvd05hbWUgLSBUaGUgbmFtZSBvZiB0aGUgd2luZG93IHRvIGdldC5cbiAqIEByZXR1cm4ge09iamVjdH0gLSBUaGUgc3BlY2lmaWVkIHdpbmRvdyBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXQod2luZG93TmFtZSkge1xuICAgIHJldHVybiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKTtcbn1cblxuLyoqXG4gKiBDZW50ZXJzIHRoZSB3aW5kb3cgb24gdGhlIHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENlbnRlcigpIHtcbiAgICB0aGlzV2luZG93LkNlbnRlcigpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIHRpdGxlIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGUgLSBUaGUgdGl0bGUgdG8gc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0VGl0bGUodGl0bGUpIHtcbiAgICB0aGlzV2luZG93LlNldFRpdGxlKHRpdGxlKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSB3aW5kb3cgdG8gZnVsbHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEZ1bGxzY3JlZW4oKSB7XG4gICAgdGhpc1dpbmRvdy5GdWxsc2NyZWVuKCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgc2l6ZSBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdGhpc1dpbmRvdy5TZXRTaXplKHdpZHRoLCBoZWlnaHQpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNpemUoKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2l6ZSgpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIG1heGltdW0gd2lkdGggb2YgdGhlIHdpbmRvdy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgLSBUaGUgbWF4aW11bSBoZWlnaHQgb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldE1heFNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXNXaW5kb3cuU2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aCAtIFRoZSBtaW5pbXVtIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIG1pbmltdW0gaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzV2luZG93LlNldE1pblNpemUod2lkdGgsIGhlaWdodCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgd2luZG93IHRvIGFsd2F5cyBiZSBvbiB0b3AuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IG9uVG9wIC0gV2hldGhlciB0aGUgd2luZG93IHNob3VsZCBhbHdheXMgYmUgb24gdG9wLlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0QWx3YXlzT25Ub3Aob25Ub3ApIHtcbiAgICB0aGlzV2luZG93LlNldEFsd2F5c09uVG9wKG9uVG9wKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSByZWxhdGl2ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHggLSBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSB3aW5kb3cncyBwb3NpdGlvbi5cbiAqIEBwYXJhbSB7bnVtYmVyfSB5IC0gVGhlIHktY29vcmRpbmF0ZSBvZiB0aGUgd2luZG93J3MgcG9zaXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRSZWxhdGl2ZVBvc2l0aW9uKHgsIHkpIHtcbiAgICB0aGlzV2luZG93LlNldFJlbGF0aXZlUG9zaXRpb24oeCwgeSk7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFJlbGF0aXZlUG9zaXRpb24oKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuUmVsYXRpdmVQb3NpdGlvbigpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNjcmVlbiB0aGF0IHRoZSB3aW5kb3cgaXMgb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTY3JlZW4oKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2NyZWVuKCk7XG59XG5cbi8qKlxuICogSGlkZXMgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XG4gICAgdGhpc1dpbmRvdy5IaWRlKCk7XG59XG5cbi8qKlxuICogTWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBNYXhpbWlzZSgpIHtcbiAgICB0aGlzV2luZG93Lk1heGltaXNlKCk7XG59XG5cbi8qKlxuICogVW4tbWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBVbk1heGltaXNlKCkge1xuICAgIHRoaXNXaW5kb3cuVW5NYXhpbWlzZSgpO1xufVxuXG4vKipcbiAqIFRvZ2dsZXMgdGhlIG1heGltaXNhdGlvbiBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gVG9nZ2xlTWF4aW1pc2UoKSB7XG4gICAgdGhpc1dpbmRvdy5Ub2dnbGVNYXhpbWlzZSgpO1xufVxuXG4vKipcbiAqIE1pbmltaXNlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gTWluaW1pc2UoKSB7XG4gICAgdGhpc1dpbmRvdy5NaW5pbWlzZSgpO1xufVxuXG4vKipcbiAqIFVuLW1pbmltaXNlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gVW5NaW5pbWlzZSgpIHtcbiAgICB0aGlzV2luZG93LlVuTWluaW1pc2UoKTtcbn1cblxuLyoqXG4gKiBSZXN0b3JlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVzdG9yZSgpIHtcbiAgICB0aGlzV2luZG93LlJlc3RvcmUoKTtcbn1cblxuLyoqXG4gKiBTaG93cyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpIHtcbiAgICB0aGlzV2luZG93LlNob3coKTtcbn1cblxuLyoqXG4gKiBDbG9zZXMgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENsb3NlKCkge1xuICAgIHRoaXNXaW5kb3cuQ2xvc2UoKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBiYWNrZ3JvdW5kIGNvbG91ciBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHIgLSBUaGUgcmVkIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxuICogQHBhcmFtIHtudW1iZXJ9IGcgLSBUaGUgZ3JlZW4gY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXG4gKiBAcGFyYW0ge251bWJlcn0gYiAtIFRoZSBibHVlIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxuICogQHBhcmFtIHtudW1iZXJ9IGEgLSBUaGUgYWxwaGEgY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRCYWNrZ3JvdW5kQ29sb3VyKHIsIGcsIGIsIGEpIHtcbiAgICB0aGlzV2luZG93LlNldEJhY2tncm91bmRDb2xvdXIociwgZywgYiwgYSk7XG59XG5cbi8qKlxuICogU2V0cyB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgcmVzaXphYmxlLlxuICogQHBhcmFtIHtib29sZWFufSByZXNpemFibGUgLSBXaGV0aGVyIHRoZSB3aW5kb3cgc2hvdWxkIGJlIHJlc2l6YWJsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldFJlc2l6YWJsZShyZXNpemFibGUpIHtcbiAgICB0aGlzV2luZG93LlNldFJlc2l6YWJsZShyZXNpemFibGUpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaWR0aCgpIHtcbiAgICByZXR1cm4gdGhpc1dpbmRvdy5XaWR0aCgpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gSGVpZ2h0KCkge1xuICAgIHJldHVybiB0aGlzV2luZG93LkhlaWdodCgpO1xufVxuXG4vKipcbiAqIFpvb21zIGluIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBab29tSW4oKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tSW4oKTtcbn1cblxuLyoqXG4gKiBab29tcyBvdXQgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFpvb21PdXQoKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tT3V0KCk7XG59XG5cbi8qKlxuICogUmVzZXRzIHRoZSB6b29tIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBab29tUmVzZXQoKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tUmVzZXQoKTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRab29tTGV2ZWwoKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuR2V0Wm9vbUxldmVsKCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHpvb21MZXZlbCAtIFRoZSB6b29tIGxldmVsIHRvIHNldC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldFpvb21MZXZlbCh6b29tTGV2ZWwpIHtcbiAgICB0aGlzV2luZG93LlNldFpvb21MZXZlbCh6b29tTGV2ZWwpO1xufVxuIiwgIlxuaW1wb3J0IHtFbWl0LCBXYWlsc0V2ZW50fSBmcm9tIFwiLi9ldmVudHNcIjtcbmltcG9ydCB7UXVlc3Rpb259IGZyb20gXCIuL2RpYWxvZ3NcIjtcbmltcG9ydCB7R2V0fSBmcm9tIFwiLi93aW5kb3dcIjtcbmltcG9ydCB7T3BlblVSTH0gZnJvbSBcIi4vYnJvd3NlclwiO1xuXG4vKipcbiAqIFNlbmRzIGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIG9wdGlvbmFsIGRhdGEuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBzZW5kLlxuICogQHBhcmFtIHthbnl9IFtkYXRhPW51bGxdIC0gT3B0aW9uYWwgZGF0YSB0byBzZW5kIGFsb25nIHdpdGggdGhlIGV2ZW50LlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHNlbmRFdmVudChldmVudE5hbWUsIGRhdGE9bnVsbCkge1xuICAgIGxldCBldmVudCA9IG5ldyBXYWlsc0V2ZW50KGV2ZW50TmFtZSwgZGF0YSk7XG4gICAgRW1pdChldmVudCk7XG59XG5cbi8qKlxuICogQWRkcyBldmVudCBsaXN0ZW5lcnMgdG8gZWxlbWVudHMgd2l0aCBgd21sLWV2ZW50YCBhdHRyaWJ1dGUuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gYWRkV01MRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLWV2ZW50XScpO1xuICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZXZlbnRUeXBlID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1ldmVudCcpO1xuICAgICAgICBjb25zdCBjb25maXJtID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1jb25maXJtJyk7XG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XG5cbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIERldGFjaGVkOiBmYWxzZSwgQnV0dG9uczpbe0xhYmVsOlwiWWVzXCJ9LHtMYWJlbDpcIk5vXCIsIElzRGVmYXVsdDp0cnVlfV19KS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPT0gXCJOb1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kRXZlbnQoZXZlbnRUeXBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbmRFdmVudChldmVudFR5cGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFJlbW92ZSBleGlzdGluZyBsaXN0ZW5lcnNcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcblxuICAgICAgICAvLyBBZGQgbmV3IGxpc3RlbmVyXG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XG4gICAgfSk7XG59XG5cblxuLyoqXG4gKiBDYWxscyBhIG1ldGhvZCBvbiBhIHNwZWNpZmllZCB3aW5kb3cuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgdG8gY2FsbCB0aGUgbWV0aG9kIG9uLlxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZCAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqL1xuZnVuY3Rpb24gY2FsbFdpbmRvd01ldGhvZCh3aW5kb3dOYW1lLCBtZXRob2QpIHtcbiAgICBsZXQgdGFyZ2V0V2luZG93ID0gR2V0KHdpbmRvd05hbWUpO1xuICAgIGxldCBtZXRob2RNYXAgPSBXaW5kb3dNZXRob2RzKHRhcmdldFdpbmRvdyk7XG4gICAgaWYgKCFtZXRob2RNYXAuaGFzKG1ldGhvZCkpIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJXaW5kb3cgbWV0aG9kIFwiICsgbWV0aG9kICsgXCIgbm90IGZvdW5kXCIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBtZXRob2RNYXAuZ2V0KG1ldGhvZCkoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBjYWxsaW5nIHdpbmRvdyBtZXRob2QgJ1wiICsgbWV0aG9kICsgXCInOiBcIiArIGUpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBZGRzIHdpbmRvdyBsaXN0ZW5lcnMgZm9yIGVsZW1lbnRzIHdpdGggdGhlICd3bWwtd2luZG93JyBhdHRyaWJ1dGUuXG4gKiBSZW1vdmVzIGFueSBleGlzdGluZyBsaXN0ZW5lcnMgYmVmb3JlIGFkZGluZyBuZXcgb25lcy5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5mdW5jdGlvbiBhZGRXTUxXaW5kb3dMaXN0ZW5lcnMoKSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLXdpbmRvd10nKTtcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IHdpbmRvd01ldGhvZCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtd2luZG93Jyk7XG4gICAgICAgIGNvbnN0IGNvbmZpcm0gPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWNvbmZpcm0nKTtcbiAgICAgICAgY29uc3QgdHJpZ2dlciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdHJpZ2dlcicpIHx8ICdjbGljayc7XG4gICAgICAgIGNvbnN0IHRhcmdldFdpbmRvdyA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdGFyZ2V0LXdpbmRvdycpIHx8ICcnO1xuXG4gICAgICAgIGxldCBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjb25maXJtKSB7XG4gICAgICAgICAgICAgICAgUXVlc3Rpb24oe1RpdGxlOiBcIkNvbmZpcm1cIiwgTWVzc2FnZTpjb25maXJtLCBCdXR0b25zOlt7TGFiZWw6XCJZZXNcIn0se0xhYmVsOlwiTm9cIiwgSXNEZWZhdWx0OnRydWV9XX0pLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9PSBcIk5vXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxXaW5kb3dNZXRob2QodGFyZ2V0V2luZG93LCB3aW5kb3dNZXRob2QpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FsbFdpbmRvd01ldGhvZCh0YXJnZXRXaW5kb3csIHdpbmRvd01ldGhvZCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUmVtb3ZlIGV4aXN0aW5nIGxpc3RlbmVyc1xuICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xuXG4gICAgICAgIC8vIEFkZCBuZXcgbGlzdGVuZXJcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBBZGRzIGEgbGlzdGVuZXIgdG8gZWxlbWVudHMgd2l0aCB0aGUgJ3dtbC1vcGVudXJsJyBhdHRyaWJ1dGUuXG4gKiBXaGVuIHRoZSBzcGVjaWZpZWQgdHJpZ2dlciBldmVudCBpcyBmaXJlZCBvbiBhbnkgb2YgdGhlc2UgZWxlbWVudHMsXG4gKiB0aGUgbGlzdGVuZXIgd2lsbCBvcGVuIHRoZSBVUkwgc3BlY2lmaWVkIGJ5IHRoZSAnd21sLW9wZW51cmwnIGF0dHJpYnV0ZS5cbiAqIElmIGEgJ3dtbC1jb25maXJtJyBhdHRyaWJ1dGUgaXMgcHJvdmlkZWQsIGEgY29uZmlybWF0aW9uIGRpYWxvZyB3aWxsIGJlIGRpc3BsYXllZCxcbiAqIGFuZCB0aGUgVVJMIHdpbGwgb25seSBiZSBvcGVuZWQgaWYgdGhlIHVzZXIgY29uZmlybXMuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpIHtcbiAgICBjb25zdCBlbGVtZW50cyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ1t3bWwtb3BlbnVybF0nKTtcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IHVybCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtb3BlbnVybCcpO1xuICAgICAgICBjb25zdCBjb25maXJtID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1jb25maXJtJyk7XG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XG5cbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIEJ1dHRvbnM6W3tMYWJlbDpcIlllc1wifSx7TGFiZWw6XCJOb1wiLCBJc0RlZmF1bHQ6dHJ1ZX1dfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT09IFwiTm9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCBPcGVuVVJMKHVybCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2b2lkIE9wZW5VUkwodXJsKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZW1vdmUgZXhpc3RpbmcgbGlzdGVuZXJzXG4gICAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XG5cbiAgICAgICAgLy8gQWRkIG5ldyBsaXN0ZW5lclxuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIFJlbG9hZHMgdGhlIFdNTCBwYWdlIGJ5IGFkZGluZyBuZWNlc3NhcnkgZXZlbnQgbGlzdGVuZXJzIGFuZCBicm93c2VyIGxpc3RlbmVycy5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVsb2FkKCkge1xuICAgIGFkZFdNTEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgYWRkV01MV2luZG93TGlzdGVuZXJzKCk7XG4gICAgYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBtYXAgb2YgYWxsIG1ldGhvZHMgaW4gdGhlIGN1cnJlbnQgd2luZG93LlxuICogQHJldHVybnMge01hcH0gLSBBIG1hcCBvZiB3aW5kb3cgbWV0aG9kcy5cbiAqL1xuZnVuY3Rpb24gV2luZG93TWV0aG9kcyh0YXJnZXRXaW5kb3cpIHtcbiAgICAvLyBDcmVhdGUgYSBuZXcgbWFwIHRvIHN0b3JlIG1ldGhvZHNcbiAgICBsZXQgcmVzdWx0ID0gbmV3IE1hcCgpO1xuXG4gICAgLy8gSXRlcmF0ZSBvdmVyIGFsbCBwcm9wZXJ0aWVzIG9mIHRoZSB3aW5kb3cgb2JqZWN0XG4gICAgZm9yIChsZXQgbWV0aG9kIGluIHRhcmdldFdpbmRvdykge1xuICAgICAgICAvLyBDaGVjayBpZiB0aGUgcHJvcGVydHkgaXMgaW5kZWVkIGEgbWV0aG9kIChmdW5jdGlvbilcbiAgICAgICAgaWYodHlwZW9mIHRhcmdldFdpbmRvd1ttZXRob2RdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAvLyBBZGQgdGhlIG1ldGhvZCB0byB0aGUgbWFwXG4gICAgICAgICAgICByZXN1bHQuc2V0KG1ldGhvZCwgdGFyZ2V0V2luZG93W21ldGhvZF0pO1xuICAgICAgICB9XG5cbiAgICB9XG4gICAgLy8gUmV0dXJuIHRoZSBtYXAgb2Ygd2luZG93IG1ldGhvZHNcbiAgICByZXR1cm4gcmVzdWx0O1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtpbXBvcnQoXCIuL3R5cGVzXCIpLldhaWxzRXZlbnR9IFdhaWxzRXZlbnRcbiAqL1xuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuXG5pbXBvcnQge0V2ZW50VHlwZXN9IGZyb20gXCIuL2V2ZW50X3R5cGVzXCI7XG5leHBvcnQgY29uc3QgVHlwZXMgPSBFdmVudFR5cGVzO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLmRpc3BhdGNoV2FpbHNFdmVudCA9IGRpc3BhdGNoV2FpbHNFdmVudDtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuRXZlbnRzLCAnJyk7XG5jb25zdCBFbWl0TWV0aG9kID0gMDtcbmNvbnN0IGV2ZW50TGlzdGVuZXJzID0gbmV3IE1hcCgpO1xuXG5jbGFzcyBMaXN0ZW5lciB7XG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgICAgIHRoaXMuZXZlbnROYW1lID0gZXZlbnROYW1lO1xuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICAgICAgdGhpcy5DYWxsYmFjayA9IChkYXRhKSA9PiB7XG4gICAgICAgICAgICBjYWxsYmFjayhkYXRhKTtcbiAgICAgICAgICAgIGlmICh0aGlzLm1heENhbGxiYWNrcyA9PT0gLTEpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMubWF4Q2FsbGJhY2tzIC09IDE7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXhDYWxsYmFja3MgPT09IDA7XG4gICAgICAgIH07XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2FpbHNFdmVudCB7XG4gICAgY29uc3RydWN0b3IobmFtZSwgZGF0YSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cCgpIHtcbn1cblxuZnVuY3Rpb24gZGlzcGF0Y2hXYWlsc0V2ZW50KGV2ZW50KSB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudC5uYW1lKTtcbiAgICBpZiAobGlzdGVuZXJzKSB7XG4gICAgICAgIGxldCB0b1JlbW92ZSA9IGxpc3RlbmVycy5maWx0ZXIobGlzdGVuZXIgPT4ge1xuICAgICAgICAgICAgbGV0IHJlbW92ZSA9IGxpc3RlbmVyLkNhbGxiYWNrKGV2ZW50KTtcbiAgICAgICAgICAgIGlmIChyZW1vdmUpIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHRvUmVtb3ZlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVycy5maWx0ZXIobCA9PiAhdG9SZW1vdmUuaW5jbHVkZXMobCkpO1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5sZW5ndGggPT09IDApIGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudC5uYW1lKTtcbiAgICAgICAgICAgIGVsc2UgZXZlbnRMaXN0ZW5lcnMuc2V0KGV2ZW50Lm5hbWUsIGxpc3RlbmVycyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogUmVnaXN0ZXIgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgbXVsdGlwbGUgdGltZXMgZm9yIGEgc3BlY2lmaWMgZXZlbnQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZWdpc3RlciB0aGUgY2FsbGJhY2sgZm9yLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIHRyaWdnZXJlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3MgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdGhlIGNhbGxiYWNrIGNhbiBiZSBjYWxsZWQgZm9yIHRoZSBldmVudC4gT25jZSB0aGUgbWF4aW11bSBudW1iZXIgaXMgcmVhY2hlZCwgdGhlIGNhbGxiYWNrIHdpbGwgbm8gbG9uZ2VyIGJlIGNhbGxlZC5cbiAqXG4gQHJldHVybiB7ZnVuY3Rpb259IC0gQSBmdW5jdGlvbiB0aGF0LCB3aGVuIGNhbGxlZCwgd2lsbCB1bnJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmcm9tIHRoZSBldmVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudE5hbWUpIHx8IFtdO1xuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xuICAgIGxpc3RlbmVycy5wdXNoKHRoaXNMaXN0ZW5lcik7XG4gICAgZXZlbnRMaXN0ZW5lcnMuc2V0KGV2ZW50TmFtZSwgbGlzdGVuZXJzKTtcbiAgICByZXR1cm4gKCkgPT4gbGlzdGVuZXJPZmYodGhpc0xpc3RlbmVyKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuIHRoZSBzcGVjaWZpZWQgZXZlbnQgb2NjdXJzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFjayAtIFRoZSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZC4gSXQgdGFrZXMgbm8gcGFyYW1ldGVycy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuICovXG5leHBvcnQgZnVuY3Rpb24gT24oZXZlbnROYW1lLCBjYWxsYmFjaykgeyByZXR1cm4gT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAtMSk7IH1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmx5IG9uY2UgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudC5cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGV2ZW50IG9jY3Vycy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHsgcmV0dXJuIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgMSk7IH1cblxuLyoqXG4gKiBSZW1vdmVzIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIgZnJvbSB0aGUgZXZlbnQgbGlzdGVuZXJzIGNvbGxlY3Rpb24uXG4gKiBJZiBhbGwgbGlzdGVuZXJzIGZvciB0aGUgZXZlbnQgYXJlIHJlbW92ZWQsIHRoZSBldmVudCBrZXkgaXMgZGVsZXRlZCBmcm9tIHRoZSBjb2xsZWN0aW9uLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBsaXN0ZW5lciAtIFRoZSBsaXN0ZW5lciB0byBiZSByZW1vdmVkLlxuICovXG5mdW5jdGlvbiBsaXN0ZW5lck9mZihsaXN0ZW5lcikge1xuICAgIGNvbnN0IGV2ZW50TmFtZSA9IGxpc3RlbmVyLmV2ZW50TmFtZTtcbiAgICBsZXQgbGlzdGVuZXJzID0gZXZlbnRMaXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSkuZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuICAgIGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSBldmVudExpc3RlbmVycy5kZWxldGUoZXZlbnROYW1lKTtcbiAgICBlbHNlIGV2ZW50TGlzdGVuZXJzLnNldChldmVudE5hbWUsIGxpc3RlbmVycyk7XG59XG5cblxuLyoqXG4gKiBSZW1vdmVzIGV2ZW50IGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudCBuYW1lcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSBsaXN0ZW5lcnMgZm9yLlxuICogQHBhcmFtIHsuLi5zdHJpbmd9IGFkZGl0aW9uYWxFdmVudE5hbWVzIC0gQWRkaXRpb25hbCBldmVudCBuYW1lcyB0byByZW1vdmUgbGlzdGVuZXJzIGZvci5cbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9mZihldmVudE5hbWUsIC4uLmFkZGl0aW9uYWxFdmVudE5hbWVzKSB7XG4gICAgbGV0IGV2ZW50c1RvUmVtb3ZlID0gW2V2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXNdO1xuICAgIGV2ZW50c1RvUmVtb3ZlLmZvckVhY2goZXZlbnROYW1lID0+IGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudE5hbWUpKTtcbn1cbi8qKlxuICogUmVtb3ZlcyBhbGwgZXZlbnQgbGlzdGVuZXJzLlxuICpcbiAqIEBmdW5jdGlvbiBPZmZBbGxcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gT2ZmQWxsKCkgeyBldmVudExpc3RlbmVycy5jbGVhcigpOyB9XG5cbi8qKlxuICogRW1pdHMgYW4gZXZlbnQgdXNpbmcgdGhlIGdpdmVuIGV2ZW50IG5hbWUuXG4gKlxuICogQHBhcmFtIHtXYWlsc0V2ZW50fSBldmVudCAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBlbWl0LlxuICogQHJldHVybnMge2FueX0gLSBUaGUgcmVzdWx0IG9mIHRoZSBlbWl0dGVkIGV2ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gRW1pdChldmVudCkgeyByZXR1cm4gY2FsbChFbWl0TWV0aG9kLCBldmVudCk7IH1cbiIsICJcbmV4cG9ydCBjb25zdCBFdmVudFR5cGVzID0ge1xuXHRXaW5kb3dzOiB7XG5cdFx0U3lzdGVtVGhlbWVDaGFuZ2VkOiBcIndpbmRvd3M6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdFx0QVBNUG93ZXJTdGF0dXNDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclN0YXR1c0NoYW5nZVwiLFxuXHRcdEFQTVN1c3BlbmQ6IFwid2luZG93czpBUE1TdXNwZW5kXCIsXG5cdFx0QVBNUmVzdW1lQXV0b21hdGljOiBcIndpbmRvd3M6QVBNUmVzdW1lQXV0b21hdGljXCIsXG5cdFx0QVBNUmVzdW1lU3VzcGVuZDogXCJ3aW5kb3dzOkFQTVJlc3VtZVN1c3BlbmRcIixcblx0XHRBUE1Qb3dlclNldHRpbmdDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclNldHRpbmdDaGFuZ2VcIixcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwid2luZG93czpBcHBsaWNhdGlvblN0YXJ0ZWRcIixcblx0XHRXZWJWaWV3TmF2aWdhdGlvbkNvbXBsZXRlZDogXCJ3aW5kb3dzOldlYlZpZXdOYXZpZ2F0aW9uQ29tcGxldGVkXCIsXG5cdFx0V2luZG93SW5hY3RpdmU6IFwid2luZG93czpXaW5kb3dJbmFjdGl2ZVwiLFxuXHRcdFdpbmRvd0FjdGl2ZTogXCJ3aW5kb3dzOldpbmRvd0FjdGl2ZVwiLFxuXHRcdFdpbmRvd0NsaWNrQWN0aXZlOiBcIndpbmRvd3M6V2luZG93Q2xpY2tBY3RpdmVcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcIndpbmRvd3M6V2luZG93RnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1VuRnVsbHNjcmVlbjogXCJ3aW5kb3dzOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwid2luZG93czpXaW5kb3dSZXN0b3JlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwid2luZG93czpXaW5kb3dNaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWluaW1pc2U6IFwid2luZG93czpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2U6IFwid2luZG93czpXaW5kb3dDbG9zZVwiLFxuXHRcdFdpbmRvd1NldEZvY3VzOiBcIndpbmRvd3M6V2luZG93U2V0Rm9jdXNcIixcblx0XHRXaW5kb3dLaWxsRm9jdXM6IFwid2luZG93czpXaW5kb3dLaWxsRm9jdXNcIixcblx0XHRXaW5kb3dEcmFnRHJvcDogXCJ3aW5kb3dzOldpbmRvd0RyYWdEcm9wXCIsXG5cdFx0V2luZG93RHJhZ0VudGVyOiBcIndpbmRvd3M6V2luZG93RHJhZ0VudGVyXCIsXG5cdFx0V2luZG93RHJhZ0xlYXZlOiBcIndpbmRvd3M6V2luZG93RHJhZ0xlYXZlXCIsXG5cdFx0V2luZG93RHJhZ092ZXI6IFwid2luZG93czpXaW5kb3dEcmFnT3ZlclwiLFxuXHR9LFxuXHRNYWM6IHtcblx0XHRBcHBsaWNhdGlvbkRpZEJlY29tZUFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUVmZmVjdGl2ZUFwcGVhcmFuY2VcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUljb246IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlSWNvblwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU2NyZWVuUGFyYW1ldGVyc1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uXCIsXG5cdFx0QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmc6IFwibWFjOkFwcGxpY2F0aW9uRGlkRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25EaWRIaWRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZEhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFJlc2lnbkFjdGl2ZU5vdGlmaWNhdGlvbjogXCJtYWM6QXBwbGljYXRpb25EaWRSZXNpZ25BY3RpdmVOb3RpZmljYXRpb25cIixcblx0XHRBcHBsaWNhdGlvbkRpZFVuaGlkZTogXCJtYWM6QXBwbGljYXRpb25EaWRVbmhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25EaWRVcGRhdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxCZWNvbWVBY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbEJlY29tZUFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEZpbmlzaExhdW5jaGluZzogXCJtYWM6QXBwbGljYXRpb25XaWxsRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsSGlkZTogXCJtYWM6QXBwbGljYXRpb25XaWxsSGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFJlc2lnbkFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVGVybWluYXRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxVbmhpZGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFVuaGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsVXBkYXRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZTogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZSFcIixcblx0XHRBcHBsaWNhdGlvblNob3VsZEhhbmRsZVJlb3BlbjogXCJtYWM6QXBwbGljYXRpb25TaG91bGRIYW5kbGVSZW9wZW4hXCIsXG5cdFx0V2luZG93RGlkQmVjb21lS2V5OiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dEaWRCZWNvbWVNYWluOiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVNYWluXCIsXG5cdFx0V2luZG93RGlkQmVnaW5TaGVldDogXCJtYWM6V2luZG93RGlkQmVnaW5TaGVldFwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUFscGhhOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VBbHBoYVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUJhY2tpbmdMb2NhdGlvbjogXCJtYWM6V2luZG93RGlkQ2hhbmdlQmFja2luZ0xvY2F0aW9uXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQmFja2luZ1Byb3BlcnRpZXM6IFwibWFjOldpbmRvd0RpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOldpbmRvd0RpZENoYW5nZU9jY2x1c2lvblN0YXRlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW46IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2U6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2VQcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5TcGFjZVByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTaGFyaW5nVHlwZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2hhcmluZ1R5cGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUaXRsZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVGl0bGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUb29sYmFyOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VUb29sYmFyXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd0RpZERlbWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dEaWRFbmRTaGVldDogXCJtYWM6V2luZG93RGlkRW5kU2hlZXRcIixcblx0XHRXaW5kb3dEaWRFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd0RpZEVudGVyRnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dEaWRFeGl0RnVsbFNjcmVlbjogXCJtYWM6V2luZG93RGlkRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEV4aXRWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd0RpZEV4cG9zZTogXCJtYWM6V2luZG93RGlkRXhwb3NlXCIsXG5cdFx0V2luZG93RGlkRm9jdXM6IFwibWFjOldpbmRvd0RpZEZvY3VzXCIsXG5cdFx0V2luZG93RGlkTWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJtYWM6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRPcmRlck9mZlNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd0RpZE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dEaWRSZXNpZ25LZXk6IFwibWFjOldpbmRvd0RpZFJlc2lnbktleVwiLFxuXHRcdFdpbmRvd0RpZFJlc2lnbk1haW46IFwibWFjOldpbmRvd0RpZFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwibWFjOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZTogXCJtYWM6V2luZG93RGlkVXBkYXRlXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd0RpZFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRpdGxlOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVRvb2xiYXJcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5XCIsXG5cdFx0V2luZG93U2hvdWxkQ2xvc2U6IFwibWFjOldpbmRvd1Nob3VsZENsb3NlIVwiLFxuXHRcdFdpbmRvd1dpbGxCZWNvbWVLZXk6IFwibWFjOldpbmRvd1dpbGxCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dXaWxsQmVjb21lTWFpbjogXCJtYWM6V2luZG93V2lsbEJlY29tZU1haW5cIixcblx0XHRXaW5kb3dXaWxsQmVnaW5TaGVldDogXCJtYWM6V2luZG93V2lsbEJlZ2luU2hlZXRcIixcblx0XHRXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93V2lsbENsb3NlOiBcIm1hYzpXaW5kb3dXaWxsQ2xvc2VcIixcblx0XHRXaW5kb3dXaWxsRGVtaW5pYXR1cml6ZTogXCJtYWM6V2luZG93V2lsbERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd1dpbGxFbnRlclZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEV4aXRGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyOiBcIm1hYzpXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsRm9jdXNcIixcblx0XHRXaW5kb3dXaWxsTWluaWF0dXJpemU6IFwibWFjOldpbmRvd1dpbGxNaW5pYXR1cml6ZVwiLFxuXHRcdFdpbmRvd1dpbGxNb3ZlOiBcIm1hYzpXaW5kb3dXaWxsTW92ZVwiLFxuXHRcdFdpbmRvd1dpbGxPcmRlck9mZlNjcmVlbjogXCJtYWM6V2luZG93V2lsbE9yZGVyT2ZmU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd1dpbGxPcmRlck9uU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbFJlc2lnbk1haW46IFwibWFjOldpbmRvd1dpbGxSZXNpZ25NYWluXCIsXG5cdFx0V2luZG93V2lsbFJlc2l6ZTogXCJtYWM6V2luZG93V2lsbFJlc2l6ZVwiLFxuXHRcdFdpbmRvd1dpbGxVbmZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsVW5mb2N1c1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVBbHBoYVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3I6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXM6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllc1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVTaGFkb3dcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlVGl0bGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVUb29sYmFyOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVG9vbGJhclwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd1dpbGxVc2VTdGFuZGFyZEZyYW1lOiBcIm1hYzpXaW5kb3dXaWxsVXNlU3RhbmRhcmRGcmFtZVwiLFxuXHRcdE1lbnVXaWxsT3BlbjogXCJtYWM6TWVudVdpbGxPcGVuXCIsXG5cdFx0TWVudURpZE9wZW46IFwibWFjOk1lbnVEaWRPcGVuXCIsXG5cdFx0TWVudURpZENsb3NlOiBcIm1hYzpNZW51RGlkQ2xvc2VcIixcblx0XHRNZW51V2lsbFNlbmRBY3Rpb246IFwibWFjOk1lbnVXaWxsU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVXaWxsSGlnaGxpZ2h0SXRlbTogXCJtYWM6TWVudVdpbGxIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudURpZEhpZ2hsaWdodEl0ZW06IFwibWFjOk1lbnVEaWRIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudVdpbGxEaXNwbGF5SXRlbTogXCJtYWM6TWVudVdpbGxEaXNwbGF5SXRlbVwiLFxuXHRcdE1lbnVEaWREaXNwbGF5SXRlbTogXCJtYWM6TWVudURpZERpc3BsYXlJdGVtXCIsXG5cdFx0TWVudVdpbGxBZGRJdGVtOiBcIm1hYzpNZW51V2lsbEFkZEl0ZW1cIixcblx0XHRNZW51RGlkQWRkSXRlbTogXCJtYWM6TWVudURpZEFkZEl0ZW1cIixcblx0XHRNZW51V2lsbFJlbW92ZUl0ZW06IFwibWFjOk1lbnVXaWxsUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVEaWRSZW1vdmVJdGVtOiBcIm1hYzpNZW51RGlkUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVXaWxsQmVnaW5UcmFja2luZzogXCJtYWM6TWVudVdpbGxCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudURpZEJlZ2luVHJhY2tpbmc6IFwibWFjOk1lbnVEaWRCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxFbmRUcmFja2luZzogXCJtYWM6TWVudVdpbGxFbmRUcmFja2luZ1wiLFxuXHRcdE1lbnVEaWRFbmRUcmFja2luZzogXCJtYWM6TWVudURpZEVuZFRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxVcGRhdGU6IFwibWFjOk1lbnVXaWxsVXBkYXRlXCIsXG5cdFx0TWVudURpZFVwZGF0ZTogXCJtYWM6TWVudURpZFVwZGF0ZVwiLFxuXHRcdE1lbnVXaWxsUG9wVXA6IFwibWFjOk1lbnVXaWxsUG9wVXBcIixcblx0XHRNZW51RGlkUG9wVXA6IFwibWFjOk1lbnVEaWRQb3BVcFwiLFxuXHRcdE1lbnVXaWxsU2VuZEFjdGlvblRvSXRlbTogXCJtYWM6TWVudVdpbGxTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0TWVudURpZFNlbmRBY3Rpb25Ub0l0ZW06IFwibWFjOk1lbnVEaWRTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0V2ViVmlld0RpZFN0YXJ0UHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkU3RhcnRQcm92aXNpb25hbE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZENvbW1pdE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRDb21taXROYXZpZ2F0aW9uXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZFwiLFxuXHRcdFdpbmRvd0ZpbGVEcmFnZ2luZ1BlcmZvcm1lZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nUGVyZm9ybWVkXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRXhpdGVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdFeGl0ZWRcIixcblx0fSxcblx0TGludXg6IHtcblx0XHRTeXN0ZW1UaGVtZUNoYW5nZWQ6IFwibGludXg6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdFx0V2luZG93TG9hZENoYW5nZWQ6IFwibGludXg6V2luZG93TG9hZENoYW5nZWRcIixcblx0XHRXaW5kb3dEZWxldGVFdmVudDogXCJsaW51eDpXaW5kb3dEZWxldGVFdmVudFwiLFxuXHRcdFdpbmRvd0ZvY3VzSW46IFwibGludXg6V2luZG93Rm9jdXNJblwiLFxuXHRcdFdpbmRvd0ZvY3VzT3V0OiBcImxpbnV4OldpbmRvd0ZvY3VzT3V0XCIsXG5cdFx0QXBwbGljYXRpb25TdGFydHVwOiBcImxpbnV4OkFwcGxpY2F0aW9uU3RhcnR1cFwiLFxuXHR9LFxuXHRDb21tb246IHtcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwiY29tbW9uOkFwcGxpY2F0aW9uU3RhcnRlZFwiLFxuXHRcdFdpbmRvd01heGltaXNlOiBcImNvbW1vbjpXaW5kb3dNYXhpbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWF4aW1pc2U6IFwiY29tbW9uOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcImNvbW1vbjpXaW5kb3dGdWxsc2NyZWVuXCIsXG5cdFx0V2luZG93VW5GdWxsc2NyZWVuOiBcImNvbW1vbjpXaW5kb3dVbkZ1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dSZXN0b3JlOiBcImNvbW1vbjpXaW5kb3dSZXN0b3JlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwiY29tbW9uOldpbmRvd01pbmltaXNlXCIsXG5cdFx0V2luZG93VW5NaW5pbWlzZTogXCJjb21tb246V2luZG93VW5NaW5pbWlzZVwiLFxuXHRcdFdpbmRvd0Nsb3Npbmc6IFwiY29tbW9uOldpbmRvd0Nsb3NpbmdcIixcblx0XHRXaW5kb3dab29tOiBcImNvbW1vbjpXaW5kb3dab29tXCIsXG5cdFx0V2luZG93Wm9vbUluOiBcImNvbW1vbjpXaW5kb3dab29tSW5cIixcblx0XHRXaW5kb3dab29tT3V0OiBcImNvbW1vbjpXaW5kb3dab29tT3V0XCIsXG5cdFx0V2luZG93Wm9vbVJlc2V0OiBcImNvbW1vbjpXaW5kb3dab29tUmVzZXRcIixcblx0XHRXaW5kb3dGb2N1czogXCJjb21tb246V2luZG93Rm9jdXNcIixcblx0XHRXaW5kb3dMb3N0Rm9jdXM6IFwiY29tbW9uOldpbmRvd0xvc3RGb2N1c1wiLFxuXHRcdFdpbmRvd1Nob3c6IFwiY29tbW9uOldpbmRvd1Nob3dcIixcblx0XHRXaW5kb3dIaWRlOiBcImNvbW1vbjpXaW5kb3dIaWRlXCIsXG5cdFx0V2luZG93RFBJQ2hhbmdlZDogXCJjb21tb246V2luZG93RFBJQ2hhbmdlZFwiLFxuXHRcdFdpbmRvd0ZpbGVzRHJvcHBlZDogXCJjb21tb246V2luZG93RmlsZXNEcm9wcGVkXCIsXG5cdFx0V2luZG93UnVudGltZVJlYWR5OiBcImNvbW1vbjpXaW5kb3dSdW50aW1lUmVhZHlcIixcblx0XHRUaGVtZUNoYW5nZWQ6IFwiY29tbW9uOlRoZW1lQ2hhbmdlZFwiLFxuXHR9LFxufTtcbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wZW5GaWxlRGlhbG9nT3B0aW9uc1xuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ2hvb3NlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjaG9zZW4uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DaG9vc2VGaWxlc10gLSBJbmRpY2F0ZXMgaWYgZmlsZXMgY2FuIGJlIGNob3Nlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNyZWF0ZURpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBkaXJlY3RvcmllcyBjYW4gYmUgY3JlYXRlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1Nob3dIaWRkZW5GaWxlc10gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGZpbGVzIHNob3VsZCBiZSBzaG93bi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1Jlc29sdmVzQWxpYXNlc10gLSBJbmRpY2F0ZXMgaWYgYWxpYXNlcyBzaG91bGQgYmUgcmVzb2x2ZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtBbGxvd3NNdWx0aXBsZVNlbGVjdGlvbl0gLSBJbmRpY2F0ZXMgaWYgbXVsdGlwbGUgc2VsZWN0aW9uIGlzIGFsbG93ZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtIaWRlRXh0ZW5zaW9uXSAtIEluZGljYXRlcyBpZiB0aGUgZXh0ZW5zaW9uIHNob3VsZCBiZSBoaWRkZW4uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5TZWxlY3RIaWRkZW5FeHRlbnNpb25dIC0gSW5kaWNhdGVzIGlmIGhpZGRlbiBleHRlbnNpb25zIGNhbiBiZSBzZWxlY3RlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1RyZWF0c0ZpbGVQYWNrYWdlc0FzRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGZpbGUgcGFja2FnZXMgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgZGlyZWN0b3JpZXMuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtBbGxvd3NPdGhlckZpbGV0eXBlc10gLSBJbmRpY2F0ZXMgaWYgb3RoZXIgZmlsZSB0eXBlcyBhcmUgYWxsb3dlZC5cbiAqIEBwcm9wZXJ0eSB7RmlsZUZpbHRlcltdfSBbRmlsdGVyc10gLSBBcnJheSBvZiBmaWxlIGZpbHRlcnMuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW1RpdGxlXSAtIFRpdGxlIG9mIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW01lc3NhZ2VdIC0gTWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0J1dHRvblRleHRdIC0gVGV4dCB0byBkaXNwbGF5IG9uIHRoZSBidXR0b24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0RpcmVjdG9yeV0gLSBEaXJlY3RvcnkgdG8gb3BlbiBpbiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbRGV0YWNoZWRdIC0gSW5kaWNhdGVzIGlmIHRoZSBkaWFsb2cgc2hvdWxkIGFwcGVhciBkZXRhY2hlZCBmcm9tIHRoZSBtYWluIHdpbmRvdy5cbiAqL1xuXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gU2F2ZUZpbGVEaWFsb2dPcHRpb25zXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0ZpbGVuYW1lXSAtIERlZmF1bHQgZmlsZW5hbWUgdG8gdXNlIGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DaG9vc2VEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNob3Nlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZUZpbGVzXSAtIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ3JlYXRlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbU2hvd0hpZGRlbkZpbGVzXSAtIEluZGljYXRlcyBpZiBoaWRkZW4gZmlsZXMgc2hvdWxkIGJlIHNob3duLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbUmVzb2x2ZXNBbGlhc2VzXSAtIEluZGljYXRlcyBpZiBhbGlhc2VzIHNob3VsZCBiZSByZXNvbHZlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c011bHRpcGxlU2VsZWN0aW9uXSAtIEluZGljYXRlcyBpZiBtdWx0aXBsZSBzZWxlY3Rpb24gaXMgYWxsb3dlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0hpZGVFeHRlbnNpb25dIC0gSW5kaWNhdGVzIGlmIHRoZSBleHRlbnNpb24gc2hvdWxkIGJlIGhpZGRlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhblNlbGVjdEhpZGRlbkV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGV4dGVuc2lvbnMgY2FuIGJlIHNlbGVjdGVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZmlsZSBwYWNrYWdlcyBzaG91bGQgYmUgdHJlYXRlZCBhcyBkaXJlY3Rvcmllcy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c090aGVyRmlsZXR5cGVzXSAtIEluZGljYXRlcyBpZiBvdGhlciBmaWxlIHR5cGVzIGFyZSBhbGxvd2VkLlxuICogQHByb3BlcnR5IHtGaWxlRmlsdGVyW119IFtGaWx0ZXJzXSAtIEFycmF5IG9mIGZpbGUgZmlsdGVycy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGl0bGUgb2YgdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbTWVzc2FnZV0gLSBNZXNzYWdlIHRvIHNob3cgaW4gdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbQnV0dG9uVGV4dF0gLSBUZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRGlyZWN0b3J5XSAtIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtEZXRhY2hlZF0gLSBJbmRpY2F0ZXMgaWYgdGhlIGRpYWxvZyBzaG91bGQgYXBwZWFyIGRldGFjaGVkIGZyb20gdGhlIG1haW4gd2luZG93LlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gTWVzc2FnZURpYWxvZ09wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGhlIHRpdGxlIG9mIHRoZSBkaWFsb2cgd2luZG93LlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtNZXNzYWdlXSAtIFRoZSBtYWluIG1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtCdXR0b25bXX0gW0J1dHRvbnNdIC0gQXJyYXkgb2YgYnV0dG9uIG9wdGlvbnMgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbRGV0YWNoZWRdIC0gVHJ1ZSBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cgKGlmIGFwcGxpY2FibGUpLlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gQnV0dG9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0xhYmVsXSAtIFRleHQgdGhhdCBhcHBlYXJzIHdpdGhpbiB0aGUgYnV0dG9uLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbSXNDYW5jZWxdIC0gVHJ1ZSBpZiB0aGUgYnV0dG9uIHNob3VsZCBjYW5jZWwgYW4gb3BlcmF0aW9uIHdoZW4gY2xpY2tlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0lzRGVmYXVsdF0gLSBUcnVlIGlmIHRoZSBidXR0b24gc2hvdWxkIGJlIHRoZSBkZWZhdWx0IGFjdGlvbiB3aGVuIHRoZSB1c2VyIHByZXNzZXMgZW50ZXIuXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBGaWxlRmlsdGVyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0Rpc3BsYXlOYW1lXSAtIERpc3BsYXkgbmFtZSBmb3IgdGhlIGZpbHRlciwgaXQgY291bGQgYmUgXCJUZXh0IEZpbGVzXCIsIFwiSW1hZ2VzXCIgZXRjLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtQYXR0ZXJuXSAtIFBhdHRlcm4gdG8gbWF0Y2ggZm9yIHRoZSBmaWx0ZXIsIGUuZy4gXCIqLnR4dDsqLm1kXCIgZm9yIHRleHQgbWFya2Rvd24gZmlsZXMuXG4gKi9cblxuLy8gc2V0dXBcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xud2luZG93Ll93YWlscy5kaWFsb2dFcnJvckNhbGxiYWNrID0gZGlhbG9nRXJyb3JDYWxsYmFjaztcbndpbmRvdy5fd2FpbHMuZGlhbG9nUmVzdWx0Q2FsbGJhY2sgPSBkaWFsb2dSZXN1bHRDYWxsYmFjaztcblxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuXG5pbXBvcnQgeyBuYW5vaWQgfSBmcm9tICduYW5vaWQvbm9uLXNlY3VyZSc7XG5cbi8vIERlZmluZSBjb25zdGFudHMgZnJvbSB0aGUgYG1ldGhvZHNgIG9iamVjdCBpbiBUaXRsZSBDYXNlXG5jb25zdCBEaWFsb2dJbmZvID0gMDtcbmNvbnN0IERpYWxvZ1dhcm5pbmcgPSAxO1xuY29uc3QgRGlhbG9nRXJyb3IgPSAyO1xuY29uc3QgRGlhbG9nUXVlc3Rpb24gPSAzO1xuY29uc3QgRGlhbG9nT3BlbkZpbGUgPSA0O1xuY29uc3QgRGlhbG9nU2F2ZUZpbGUgPSA1O1xuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5EaWFsb2csICcnKTtcbmNvbnN0IGRpYWxvZ1Jlc3BvbnNlcyA9IG5ldyBNYXAoKTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgaWQgdGhhdCBpcyBub3QgcHJlc2VudCBpbiBkaWFsb2dSZXNwb25zZXMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSB1bmlxdWUgaWRcbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVJRCgpIHtcbiAgICBsZXQgcmVzdWx0O1xuICAgIGRvIHtcbiAgICAgICAgcmVzdWx0ID0gbmFub2lkKCk7XG4gICAgfSB3aGlsZSAoZGlhbG9nUmVzcG9uc2VzLmhhcyhyZXN1bHQpKTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIFNob3dzIGEgZGlhbG9nIG9mIHNwZWNpZmllZCB0eXBlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gKiBAcGFyYW0ge251bWJlcn0gdHlwZSAtIHR5cGUgb2YgZGlhbG9nXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfE9wZW5GaWxlRGlhbG9nT3B0aW9uc3xTYXZlRmlsZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBvcHRpb25zIGZvciB0aGUgZGlhbG9nXG4gKiBAcmV0dXJucyB7UHJvbWlzZX0gcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggcmVzdWx0IG9mIGRpYWxvZ1xuICovXG5mdW5jdGlvbiBkaWFsb2codHlwZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgaWQgPSBnZW5lcmF0ZUlEKCk7XG4gICAgb3B0aW9uc1tcImRpYWxvZy1pZFwiXSA9IGlkO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5zZXQoaWQsIHtyZXNvbHZlLCByZWplY3R9KTtcbiAgICAgICAgY2FsbCh0eXBlLCBvcHRpb25zKS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICBkaWFsb2dSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogSGFuZGxlcyB0aGUgY2FsbGJhY2sgZnJvbSBhIGRpYWxvZy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBUaGUgSUQgb2YgdGhlIGRpYWxvZyByZXNwb25zZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhIC0gVGhlIGRhdGEgcmVjZWl2ZWQgZnJvbSB0aGUgZGlhbG9nLlxuICogQHBhcmFtIHtib29sZWFufSBpc0pTT04gLSBGbGFnIGluZGljYXRpbmcgd2hldGhlciB0aGUgZGF0YSBpcyBpbiBKU09OIGZvcm1hdC5cbiAqXG4gKiBAcmV0dXJuIHt1bmRlZmluZWR9XG4gKi9cbmZ1bmN0aW9uIGRpYWxvZ1Jlc3VsdENhbGxiYWNrKGlkLCBkYXRhLCBpc0pTT04pIHtcbiAgICBsZXQgcCA9IGRpYWxvZ1Jlc3BvbnNlcy5nZXQoaWQpO1xuICAgIGlmIChwKSB7XG4gICAgICAgIGlmIChpc0pTT04pIHtcbiAgICAgICAgICAgIHAucmVzb2x2ZShKU09OLnBhcnNlKGRhdGEpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHAucmVzb2x2ZShkYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBkaWFsb2dSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICB9XG59XG5cbi8qKlxuICogQ2FsbGJhY2sgZnVuY3Rpb24gZm9yIGhhbmRsaW5nIGVycm9ycyBpbiBkaWFsb2cuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSBkaWFsb2cgcmVzcG9uc2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIFRoZSBlcnJvciBtZXNzYWdlLlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGRpYWxvZ0Vycm9yQ2FsbGJhY2soaWQsIG1lc3NhZ2UpIHtcbiAgICBsZXQgcCA9IGRpYWxvZ1Jlc3BvbnNlcy5nZXQoaWQpO1xuICAgIGlmIChwKSB7XG4gICAgICAgIHAucmVqZWN0KG1lc3NhZ2UpO1xuICAgICAgICBkaWFsb2dSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICB9XG59XG5cblxuLy8gUmVwbGFjZSBgbWV0aG9kc2Agd2l0aCBjb25zdGFudHMgaW4gVGl0bGUgQ2FzZVxuXG4vKipcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gLSBUaGUgbGFiZWwgb2YgdGhlIGJ1dHRvbiBwcmVzc2VkXG4gKi9cbmV4cG9ydCBjb25zdCBJbmZvID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dJbmZvLCBvcHRpb25zKTtcblxuLyoqXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gVGhlIGxhYmVsIG9mIHRoZSBidXR0b24gcHJlc3NlZFxuICovXG5leHBvcnQgY29uc3QgV2FybmluZyA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nV2FybmluZywgb3B0aW9ucyk7XG5cbi8qKlxuICogQHBhcmFtIHtNZXNzYWdlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcbiAqL1xuZXhwb3J0IGNvbnN0IEVycm9yID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dFcnJvciwgb3B0aW9ucyk7XG5cbi8qKlxuICogQHBhcmFtIHtNZXNzYWdlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcbiAqL1xuZXhwb3J0IGNvbnN0IFF1ZXN0aW9uID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dRdWVzdGlvbiwgb3B0aW9ucyk7XG5cbi8qKlxuICogQHBhcmFtIHtPcGVuRmlsZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nW118c3RyaW5nPn0gUmV0dXJucyBzZWxlY3RlZCBmaWxlIG9yIGxpc3Qgb2YgZmlsZXMuIFJldHVybnMgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaXMgc2VsZWN0ZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBPcGVuRmlsZSA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nT3BlbkZpbGUsIG9wdGlvbnMpO1xuXG4vKipcbiAqIEBwYXJhbSB7U2F2ZUZpbGVEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IFJldHVybnMgdGhlIHNlbGVjdGVkIGZpbGUuIFJldHVybnMgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaXMgc2VsZWN0ZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBTYXZlRmlsZSA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nU2F2ZUZpbGUsIG9wdGlvbnMpO1xuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQgeyBuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lcyB9IGZyb20gXCIuL3J1bnRpbWVcIjtcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZC9ub24tc2VjdXJlJztcblxuLy8gU2V0dXBcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xud2luZG93Ll93YWlscy5jYWxsUmVzdWx0SGFuZGxlciA9IHJlc3VsdEhhbmRsZXI7XG53aW5kb3cuX3dhaWxzLmNhbGxFcnJvckhhbmRsZXIgPSBlcnJvckhhbmRsZXI7XG5cblxuY29uc3QgQ2FsbEJpbmRpbmcgPSAwO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ2FsbCwgJycpO1xubGV0IGNhbGxSZXNwb25zZXMgPSBuZXcgTWFwKCk7XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgdW5pcXVlIElEIHVzaW5nIHRoZSBuYW5vaWQgbGlicmFyeS5cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IC0gQSB1bmlxdWUgSUQgdGhhdCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgY2FsbFJlc3BvbnNlcyBzZXQuXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlSUQoKSB7XG4gICAgbGV0IHJlc3VsdDtcbiAgICBkbyB7XG4gICAgICAgIHJlc3VsdCA9IG5hbm9pZCgpO1xuICAgIH0gd2hpbGUgKGNhbGxSZXNwb25zZXMuaGFzKHJlc3VsdCkpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogSGFuZGxlcyB0aGUgcmVzdWx0IG9mIGEgY2FsbCByZXF1ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFRoZSBpZCBvZiB0aGUgcmVxdWVzdCB0byBoYW5kbGUgdGhlIHJlc3VsdCBmb3IuXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YSAtIFRoZSByZXN1bHQgZGF0YSBvZiB0aGUgcmVxdWVzdC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNKU09OIC0gSW5kaWNhdGVzIHdoZXRoZXIgdGhlIGRhdGEgaXMgSlNPTiBvciBub3QuXG4gKlxuICogQHJldHVybiB7dW5kZWZpbmVkfSAtIFRoaXMgbWV0aG9kIGRvZXMgbm90IHJldHVybiBhbnkgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIHJlc3VsdEhhbmRsZXIoaWQsIGRhdGEsIGlzSlNPTikge1xuICAgIGNvbnN0IHByb21pc2VIYW5kbGVyID0gZ2V0QW5kRGVsZXRlUmVzcG9uc2UoaWQpO1xuICAgIGlmIChwcm9taXNlSGFuZGxlcikge1xuICAgICAgICBwcm9taXNlSGFuZGxlci5yZXNvbHZlKGlzSlNPTiA/IEpTT04ucGFyc2UoZGF0YSkgOiBkYXRhKTtcbiAgICB9XG59XG5cbi8qKlxuICogSGFuZGxlcyB0aGUgZXJyb3IgZnJvbSBhIGNhbGwgcmVxdWVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBUaGUgaWQgb2YgdGhlIHByb21pc2UgaGFuZGxlci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UgdG8gcmVqZWN0IHRoZSBwcm9taXNlIGhhbmRsZXIgd2l0aC5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5mdW5jdGlvbiBlcnJvckhhbmRsZXIoaWQsIG1lc3NhZ2UpIHtcbiAgICBjb25zdCBwcm9taXNlSGFuZGxlciA9IGdldEFuZERlbGV0ZVJlc3BvbnNlKGlkKTtcbiAgICBpZiAocHJvbWlzZUhhbmRsZXIpIHtcbiAgICAgICAgcHJvbWlzZUhhbmRsZXIucmVqZWN0KG1lc3NhZ2UpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZXRyaWV2ZXMgYW5kIHJlbW92ZXMgdGhlIHJlc3BvbnNlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gSUQgZnJvbSB0aGUgY2FsbFJlc3BvbnNlcyBtYXAuXG4gKlxuICogQHBhcmFtIHthbnl9IGlkIC0gVGhlIElEIG9mIHRoZSByZXNwb25zZSB0byBiZSByZXRyaWV2ZWQgYW5kIHJlbW92ZWQuXG4gKlxuICogQHJldHVybnMge2FueX0gVGhlIHJlc3BvbnNlIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIElELlxuICovXG5mdW5jdGlvbiBnZXRBbmREZWxldGVSZXNwb25zZShpZCkge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gY2FsbFJlc3BvbnNlcy5nZXQoaWQpO1xuICAgIGNhbGxSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICByZXR1cm4gcmVzcG9uc2U7XG59XG5cbi8qKlxuICogRXhlY3V0ZXMgYSBjYWxsIHVzaW5nIHRoZSBwcm92aWRlZCB0eXBlIGFuZCBvcHRpb25zLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gdHlwZSAtIFRoZSB0eXBlIG9mIGNhbGwgdG8gZXhlY3V0ZS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gLSBBZGRpdGlvbmFsIG9wdGlvbnMgZm9yIHRoZSBjYWxsLlxuICogQHJldHVybiB7UHJvbWlzZX0gLSBBIHByb21pc2UgdGhhdCB3aWxsIGJlIHJlc29sdmVkIG9yIHJlamVjdGVkIGJhc2VkIG9uIHRoZSByZXN1bHQgb2YgdGhlIGNhbGwuXG4gKi9cbmZ1bmN0aW9uIGNhbGxCaW5kaW5nKHR5cGUsIG9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGNvbnN0IGlkID0gZ2VuZXJhdGVJRCgpO1xuICAgICAgICBvcHRpb25zW1wiY2FsbC1pZFwiXSA9IGlkO1xuICAgICAgICBjYWxsUmVzcG9uc2VzLnNldChpZCwgeyByZXNvbHZlLCByZWplY3QgfSk7XG4gICAgICAgIGNhbGwodHlwZSwgb3B0aW9ucykuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgY2FsbFJlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBDYWxsIG1ldGhvZC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIFRoZSBvcHRpb25zIGZvciB0aGUgbWV0aG9kLlxuICogQHJldHVybnMge09iamVjdH0gLSBUaGUgcmVzdWx0IG9mIHRoZSBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQ2FsbChvcHRpb25zKSB7XG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCBvcHRpb25zKTtcbn1cblxuLyoqXG4gKiBFeGVjdXRlcyBhIG1ldGhvZCBieSBuYW1lLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIG1ldGhvZCBpbiB0aGUgZm9ybWF0ICdwYWNrYWdlLnN0cnVjdC5tZXRob2QnLlxuICogQHBhcmFtIHsuLi4qfSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIG5hbWUgaXMgbm90IGEgc3RyaW5nIG9yIGlzIG5vdCBpbiB0aGUgY29ycmVjdCBmb3JtYXQuXG4gKiBAcmV0dXJucyB7Kn0gVGhlIHJlc3VsdCBvZiB0aGUgbWV0aG9kIGV4ZWN1dGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEJ5TmFtZShuYW1lLCAuLi5hcmdzKSB7XG4gICAgaWYgKHR5cGVvZiBuYW1lICE9PSBcInN0cmluZ1wiIHx8IG5hbWUuc3BsaXQoXCIuXCIpLmxlbmd0aCAhPT0gMykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYWxsQnlOYW1lIHJlcXVpcmVzIGEgc3RyaW5nIGluIHRoZSBmb3JtYXQgJ3BhY2thZ2Uuc3RydWN0Lm1ldGhvZCdcIik7XG4gICAgfVxuICAgIGxldCBbcGFja2FnZU5hbWUsIHN0cnVjdE5hbWUsIG1ldGhvZE5hbWVdID0gbmFtZS5zcGxpdChcIi5cIik7XG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XG4gICAgICAgIHBhY2thZ2VOYW1lLFxuICAgICAgICBzdHJ1Y3ROYW1lLFxuICAgICAgICBtZXRob2ROYW1lLFxuICAgICAgICBhcmdzXG4gICAgfSk7XG59XG5cbi8qKlxuICogQ2FsbHMgYSBtZXRob2QgYnkgaXRzIElEIHdpdGggdGhlIHNwZWNpZmllZCBhcmd1bWVudHMuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IG1ldGhvZElEIC0gVGhlIElEIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqIEBwYXJhbSB7Li4uKn0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxuICogQHJldHVybiB7Kn0gLSBUaGUgcmVzdWx0IG9mIHRoZSBtZXRob2QgY2FsbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEJ5SUQobWV0aG9kSUQsIC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gY2FsbEJpbmRpbmcoQ2FsbEJpbmRpbmcsIHtcbiAgICAgICAgbWV0aG9kSUQsXG4gICAgICAgIGFyZ3NcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBDYWxscyBhIG1ldGhvZCBvbiBhIHBsdWdpbi5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGx1Z2luTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwbHVnaW4uXG4gKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqIEBwYXJhbSB7Li4uKn0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxuICogQHJldHVybnMgeyp9IC0gVGhlIHJlc3VsdCBvZiB0aGUgbWV0aG9kIGNhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBQbHVnaW4ocGx1Z2luTmFtZSwgbWV0aG9kTmFtZSwgLi4uYXJncykge1xuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywge1xuICAgICAgICBwYWNrYWdlTmFtZTogXCJ3YWlscy1wbHVnaW5zXCIsXG4gICAgICAgIHN0cnVjdE5hbWU6IHBsdWdpbk5hbWUsXG4gICAgICAgIG1ldGhvZE5hbWUsXG4gICAgICAgIGFyZ3NcbiAgICB9KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHtkZWJ1Z0xvZ30gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZ1wiO1xuXG53aW5kb3cuX3dhaWxzID0gd2luZG93Ll93YWlscyB8fCB7fTtcblxuaW1wb3J0ICogYXMgQXBwbGljYXRpb24gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2FwcGxpY2F0aW9uXCI7XG5pbXBvcnQgKiBhcyBCcm93c2VyIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9icm93c2VyXCI7XG5pbXBvcnQgKiBhcyBDbGlwYm9hcmQgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZFwiO1xuaW1wb3J0ICogYXMgQ29udGV4dE1lbnUgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NvbnRleHRtZW51XCI7XG5pbXBvcnQgKiBhcyBEcmFnIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9kcmFnXCI7XG5pbXBvcnQgKiBhcyBGbGFncyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3NcIjtcbmltcG9ydCAqIGFzIFNjcmVlbnMgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3NjcmVlbnNcIjtcbmltcG9ydCAqIGFzIFN5c3RlbSBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvc3lzdGVtXCI7XG5pbXBvcnQgKiBhcyBXaW5kb3cgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dpbmRvd1wiO1xuaW1wb3J0ICogYXMgV01MIGZyb20gJy4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dtbCc7XG5pbXBvcnQgKiBhcyBFdmVudHMgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50c1wiO1xuaW1wb3J0ICogYXMgRGlhbG9ncyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZGlhbG9nc1wiO1xuaW1wb3J0ICogYXMgQ2FsbCBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvY2FsbHNcIjtcbmltcG9ydCB7aW52b2tlfSBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvc3lzdGVtXCI7XG5cbi8qKipcbiBUaGlzIHRlY2huaXF1ZSBmb3IgcHJvcGVyIGxvYWQgZGV0ZWN0aW9uIGlzIHRha2VuIGZyb20gSFRNWDpcblxuIEJTRCAyLUNsYXVzZSBMaWNlbnNlXG5cbiBDb3B5cmlnaHQgKGMpIDIwMjAsIEJpZyBTa3kgU29mdHdhcmVcbiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG4gUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0XG4gbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cblxuIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uXG4gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG5cbiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIlxuIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEVcbiBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcbiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFXG4gRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUxcbiBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUlxuIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSXG4gQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSxcbiBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRVxuIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG5cbiAqKiovXG5cbndpbmRvdy5fd2FpbHMuaW52b2tlPWludm9rZTtcblxud2luZG93LndhaWxzID0gd2luZG93LndhaWxzIHx8IHt9O1xud2luZG93LndhaWxzLkFwcGxpY2F0aW9uID0gQXBwbGljYXRpb247XG53aW5kb3cud2FpbHMuQnJvd3NlciA9IEJyb3dzZXI7XG53aW5kb3cud2FpbHMuQ2FsbCA9IENhbGw7XG53aW5kb3cud2FpbHMuQ2xpcGJvYXJkID0gQ2xpcGJvYXJkO1xud2luZG93LndhaWxzLkRpYWxvZ3MgPSBEaWFsb2dzO1xud2luZG93LndhaWxzLkV2ZW50cyA9IEV2ZW50cztcbndpbmRvdy53YWlscy5GbGFncyA9IEZsYWdzO1xud2luZG93LndhaWxzLlNjcmVlbnMgPSBTY3JlZW5zO1xud2luZG93LndhaWxzLlN5c3RlbSA9IFN5c3RlbTtcbndpbmRvdy53YWlscy5XaW5kb3cgPSBXaW5kb3c7XG53aW5kb3cud2FpbHMuV01MID0gV01MO1xuXG5cbmxldCBpc1JlYWR5ID0gZmFsc2VcbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCBmdW5jdGlvbigpIHtcbiAgICBpc1JlYWR5ID0gdHJ1ZVxuICAgIHdpbmRvdy5fd2FpbHMuaW52b2tlKCd3YWlsczpydW50aW1lOnJlYWR5Jyk7XG4gICAgaWYoREVCVUcpIHtcbiAgICAgICAgZGVidWdMb2coXCJXYWlscyBSdW50aW1lIExvYWRlZFwiKTtcbiAgICB9XG59KVxuXG5mdW5jdGlvbiB3aGVuUmVhZHkoZm4pIHtcbiAgICBpZiAoaXNSZWFkeSB8fCBkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnY29tcGxldGUnKSB7XG4gICAgICAgIGZuKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGZuKTtcbiAgICB9XG59XG5cbndoZW5SZWFkeSgoKSA9PiB7XG4gICAgV01MLlJlbG9hZCgpO1xufSk7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7OztBQUtPLFdBQVMsU0FBUyxTQUFTO0FBRTlCLFlBQVE7QUFBQSxNQUNKLGtCQUFrQixVQUFVO0FBQUEsTUFDNUI7QUFBQSxNQUNBO0FBQUEsSUFDSjtBQUFBLEVBQ0o7OztBQ1pBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7O0FDQUEsTUFBSSxjQUNGO0FBV0ssTUFBSSxTQUFTLENBQUNBLFFBQU8sT0FBTztBQUNqQyxRQUFJLEtBQUs7QUFDVCxRQUFJLElBQUlBO0FBQ1IsV0FBTyxLQUFLO0FBQ1YsWUFBTSxZQUFhLEtBQUssT0FBTyxJQUFJLEtBQU0sQ0FBQztBQUFBLElBQzVDO0FBQ0EsV0FBTztBQUFBLEVBQ1Q7OztBQ05BLE1BQU0sYUFBYSxPQUFPLFNBQVMsU0FBUztBQUdyQyxNQUFNLGNBQWM7QUFBQSxJQUN2QixNQUFNO0FBQUEsSUFDTixXQUFXO0FBQUEsSUFDWCxhQUFhO0FBQUEsSUFDYixRQUFRO0FBQUEsSUFDUixhQUFhO0FBQUEsSUFDYixRQUFRO0FBQUEsSUFDUixRQUFRO0FBQUEsSUFDUixTQUFTO0FBQUEsSUFDVCxRQUFRO0FBQUEsSUFDUixTQUFTO0FBQUEsRUFDYjtBQUNPLE1BQUksV0FBVyxPQUFPO0FBc0J0QixXQUFTLHVCQUF1QixRQUFRLFlBQVk7QUFDdkQsV0FBTyxTQUFVLFFBQVEsT0FBSyxNQUFNO0FBQ2hDLGFBQU8sa0JBQWtCLFFBQVEsUUFBUSxZQUFZLElBQUk7QUFBQSxJQUM3RDtBQUFBLEVBQ0o7QUFxQ0EsV0FBUyxrQkFBa0IsVUFBVSxRQUFRLFlBQVksTUFBTTtBQUMzRCxRQUFJLE1BQU0sSUFBSSxJQUFJLFVBQVU7QUFDNUIsUUFBSSxhQUFhLE9BQU8sVUFBVSxRQUFRO0FBQzFDLFFBQUksYUFBYSxPQUFPLFVBQVUsTUFBTTtBQUN4QyxRQUFJLGVBQWU7QUFBQSxNQUNmLFNBQVMsQ0FBQztBQUFBLElBQ2Q7QUFDQSxRQUFJLFlBQVk7QUFDWixtQkFBYSxRQUFRLHFCQUFxQixJQUFJO0FBQUEsSUFDbEQ7QUFDQSxRQUFJLE1BQU07QUFDTixVQUFJLGFBQWEsT0FBTyxRQUFRLEtBQUssVUFBVSxJQUFJLENBQUM7QUFBQSxJQUN4RDtBQUNBLGlCQUFhLFFBQVEsbUJBQW1CLElBQUk7QUFDNUMsV0FBTyxJQUFJLFFBQVEsQ0FBQyxTQUFTLFdBQVc7QUFDcEMsWUFBTSxLQUFLLFlBQVksRUFDbEIsS0FBSyxjQUFZO0FBQ2QsWUFBSSxTQUFTLElBQUk7QUFFYixjQUFJLFNBQVMsUUFBUSxJQUFJLGNBQWMsS0FBSyxTQUFTLFFBQVEsSUFBSSxjQUFjLEVBQUUsUUFBUSxrQkFBa0IsTUFBTSxJQUFJO0FBQ2pILG1CQUFPLFNBQVMsS0FBSztBQUFBLFVBQ3pCLE9BQU87QUFDSCxtQkFBTyxTQUFTLEtBQUs7QUFBQSxVQUN6QjtBQUFBLFFBQ0o7QUFDQSxlQUFPLE1BQU0sU0FBUyxVQUFVLENBQUM7QUFBQSxNQUNyQyxDQUFDLEVBQ0EsS0FBSyxVQUFRLFFBQVEsSUFBSSxDQUFDLEVBQzFCLE1BQU0sV0FBUyxPQUFPLEtBQUssQ0FBQztBQUFBLElBQ3JDLENBQUM7QUFBQSxFQUNMOzs7QUY1R0EsTUFBTSxPQUFPLHVCQUF1QixZQUFZLGFBQWEsRUFBRTtBQUUvRCxNQUFNLGFBQWE7QUFDbkIsTUFBTSxhQUFhO0FBQ25CLE1BQU0sYUFBYTtBQVFaLFdBQVMsT0FBTztBQUNuQixXQUFPLEtBQUssVUFBVTtBQUFBLEVBQzFCO0FBT08sV0FBUyxPQUFPO0FBQ25CLFdBQU8sS0FBSyxVQUFVO0FBQUEsRUFDMUI7QUFPTyxXQUFTLE9BQU87QUFDbkIsV0FBTyxLQUFLLFVBQVU7QUFBQSxFQUMxQjs7O0FHN0NBO0FBQUE7QUFBQTtBQUFBO0FBYUEsTUFBTUMsUUFBTyx1QkFBdUIsWUFBWSxTQUFTLEVBQUU7QUFDM0QsTUFBTSxpQkFBaUI7QUFPaEIsV0FBUyxRQUFRLEtBQUs7QUFDekIsV0FBT0EsTUFBSyxnQkFBZ0IsRUFBQyxJQUFHLENBQUM7QUFBQSxFQUNyQzs7O0FDdkJBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFjQSxNQUFNQyxRQUFPLHVCQUF1QixZQUFZLFdBQVcsRUFBRTtBQUM3RCxNQUFNLG1CQUFtQjtBQUN6QixNQUFNLGdCQUFnQjtBQVFmLFdBQVMsUUFBUSxNQUFNO0FBQzFCLFdBQU9BLE1BQUssa0JBQWtCLEVBQUMsS0FBSSxDQUFDO0FBQUEsRUFDeEM7QUFNTyxXQUFTLE9BQU87QUFDbkIsV0FBT0EsTUFBSyxhQUFhO0FBQUEsRUFDN0I7OztBQ2xDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBYUEsTUFBSUMsUUFBTyx1QkFBdUIsWUFBWSxRQUFRLEVBQUU7QUFDeEQsTUFBTSxtQkFBbUI7QUFDekIsTUFBTSxjQUFjO0FBRWIsV0FBUyxPQUFPLEtBQUs7QUFDeEIsUUFBRyxPQUFPLFFBQVE7QUFDZCxhQUFPLE9BQU8sT0FBTyxRQUFRLFlBQVksR0FBRztBQUFBLElBQ2hEO0FBQ0EsV0FBTyxPQUFPLE9BQU8sZ0JBQWdCLFNBQVMsWUFBWSxHQUFHO0FBQUEsRUFDakU7QUFPTyxXQUFTLGFBQWE7QUFDekIsV0FBT0EsTUFBSyxnQkFBZ0I7QUFBQSxFQUNoQztBQVNPLFdBQVMsZUFBZTtBQUMzQixRQUFJLFdBQVcsTUFBTSxxQkFBcUI7QUFDMUMsV0FBTyxTQUFTLEtBQUs7QUFBQSxFQUN6QjtBQWFPLFdBQVMsY0FBYztBQUMxQixXQUFPQSxNQUFLLFdBQVc7QUFBQSxFQUMzQjtBQU9PLFdBQVMsWUFBWTtBQUN4QixXQUFPLE9BQU8sT0FBTyxZQUFZLE9BQU87QUFBQSxFQUM1QztBQU9PLFdBQVMsVUFBVTtBQUN0QixXQUFPLE9BQU8sT0FBTyxZQUFZLE9BQU87QUFBQSxFQUM1QztBQU9PLFdBQVMsUUFBUTtBQUNwQixXQUFPLE9BQU8sT0FBTyxZQUFZLE9BQU87QUFBQSxFQUM1QztBQU1PLFdBQVMsVUFBVTtBQUN0QixXQUFPLE9BQU8sT0FBTyxZQUFZLFNBQVM7QUFBQSxFQUM5QztBQU9PLFdBQVMsUUFBUTtBQUNwQixXQUFPLE9BQU8sT0FBTyxZQUFZLFNBQVM7QUFBQSxFQUM5QztBQU9PLFdBQVMsVUFBVTtBQUN0QixXQUFPLE9BQU8sT0FBTyxZQUFZLFNBQVM7QUFBQSxFQUM5QztBQUVPLFdBQVMsVUFBVTtBQUN0QixXQUFPLE9BQU8sT0FBTyxZQUFZLFVBQVU7QUFBQSxFQUMvQzs7O0FDbkdBLFNBQU8saUJBQWlCLGVBQWUsa0JBQWtCO0FBRXpELE1BQU1DLFFBQU8sdUJBQXVCLFlBQVksYUFBYSxFQUFFO0FBQy9ELE1BQU0sa0JBQWtCO0FBRXhCLFdBQVMsZ0JBQWdCLElBQUksR0FBRyxHQUFHLE1BQU07QUFDckMsU0FBS0EsTUFBSyxpQkFBaUIsRUFBQyxJQUFJLEdBQUcsR0FBRyxLQUFJLENBQUM7QUFBQSxFQUMvQztBQUVBLFdBQVMsbUJBQW1CLE9BQU87QUFFL0IsUUFBSSxVQUFVLE1BQU07QUFDcEIsUUFBSSxvQkFBb0IsT0FBTyxpQkFBaUIsT0FBTyxFQUFFLGlCQUFpQixzQkFBc0I7QUFDaEcsd0JBQW9CLG9CQUFvQixrQkFBa0IsS0FBSyxJQUFJO0FBQ25FLFFBQUksbUJBQW1CO0FBQ25CLFlBQU0sZUFBZTtBQUNyQixVQUFJLHdCQUF3QixPQUFPLGlCQUFpQixPQUFPLEVBQUUsaUJBQWlCLDJCQUEyQjtBQUN6RyxzQkFBZ0IsbUJBQW1CLE1BQU0sU0FBUyxNQUFNLFNBQVMscUJBQXFCO0FBQ3RGO0FBQUEsSUFDSjtBQUVBLDhCQUEwQixLQUFLO0FBQUEsRUFDbkM7QUFVQSxXQUFTLDBCQUEwQixPQUFPO0FBR3RDLFFBQUksUUFBUSxHQUFHO0FBQ1g7QUFBQSxJQUNKO0FBR0EsVUFBTSxVQUFVLE1BQU07QUFDdEIsVUFBTSxnQkFBZ0IsT0FBTyxpQkFBaUIsT0FBTztBQUNyRCxVQUFNLDJCQUEyQixjQUFjLGlCQUFpQix1QkFBdUIsRUFBRSxLQUFLO0FBQzlGLFlBQVEsMEJBQTBCO0FBQUEsTUFDOUIsS0FBSztBQUNEO0FBQUEsTUFDSixLQUFLO0FBQ0QsY0FBTSxlQUFlO0FBQ3JCO0FBQUEsTUFDSjtBQUVJLFlBQUksUUFBUSxtQkFBbUI7QUFDM0I7QUFBQSxRQUNKO0FBR0EsY0FBTSxZQUFZLE9BQU8sYUFBYTtBQUN0QyxjQUFNLGVBQWdCLFVBQVUsU0FBUyxFQUFFLFNBQVM7QUFDcEQsWUFBSSxjQUFjO0FBQ2QsbUJBQVMsSUFBSSxHQUFHLElBQUksVUFBVSxZQUFZLEtBQUs7QUFDM0Msa0JBQU0sUUFBUSxVQUFVLFdBQVcsQ0FBQztBQUNwQyxrQkFBTSxRQUFRLE1BQU0sZUFBZTtBQUNuQyxxQkFBUyxJQUFJLEdBQUcsSUFBSSxNQUFNLFFBQVEsS0FBSztBQUNuQyxvQkFBTSxPQUFPLE1BQU0sQ0FBQztBQUNwQixrQkFBSSxTQUFTLGlCQUFpQixLQUFLLE1BQU0sS0FBSyxHQUFHLE1BQU0sU0FBUztBQUM1RDtBQUFBLGNBQ0o7QUFBQSxZQUNKO0FBQUEsVUFDSjtBQUFBLFFBQ0o7QUFFQSxZQUFJLFFBQVEsWUFBWSxXQUFXLFFBQVEsWUFBWSxZQUFZO0FBQy9ELGNBQUksZ0JBQWlCLENBQUMsUUFBUSxZQUFZLENBQUMsUUFBUSxVQUFXO0FBQzFEO0FBQUEsVUFDSjtBQUFBLFFBQ0o7QUFHQSxjQUFNLGVBQWU7QUFBQSxJQUM3QjtBQUFBLEVBQ0o7OztBQ2hHQTtBQUFBO0FBQUE7QUFBQTtBQWtCTyxXQUFTLFFBQVEsV0FBVztBQUMvQixRQUFJO0FBQ0EsYUFBTyxPQUFPLE9BQU8sTUFBTSxTQUFTO0FBQUEsSUFDeEMsU0FBUyxHQUFHO0FBQ1IsWUFBTSxJQUFJLE1BQU0sOEJBQThCLFlBQVksUUFBUSxDQUFDO0FBQUEsSUFDdkU7QUFBQSxFQUNKOzs7QUNSQSxTQUFPLFNBQVMsT0FBTyxVQUFVLENBQUM7QUFDbEMsU0FBTyxPQUFPLGVBQWU7QUFDN0IsU0FBTyxPQUFPLFVBQVU7QUFDeEIsU0FBTyxpQkFBaUIsYUFBYSxXQUFXO0FBQ2hELFNBQU8saUJBQWlCLGFBQWEsV0FBVztBQUNoRCxTQUFPLGlCQUFpQixXQUFXLFNBQVM7QUFHNUMsTUFBSSxhQUFhO0FBQ2pCLE1BQUksYUFBYTtBQUNqQixNQUFJLFlBQVk7QUFDaEIsTUFBSSxnQkFBZ0I7QUFFcEIsV0FBUyxTQUFTLEdBQUc7QUFDakIsUUFBSSxNQUFNLE9BQU8saUJBQWlCLEVBQUUsTUFBTSxFQUFFLGlCQUFpQixxQkFBcUI7QUFDbEYsUUFBSSxDQUFDLE9BQU8sUUFBUSxNQUFNLElBQUksS0FBSyxNQUFNLFVBQVUsRUFBRSxZQUFZLEdBQUc7QUFDaEUsYUFBTztBQUFBLElBQ1g7QUFDQSxXQUFPLEVBQUUsV0FBVztBQUFBLEVBQ3hCO0FBRUEsV0FBUyxhQUFhLE9BQU87QUFDekIsZ0JBQVk7QUFBQSxFQUNoQjtBQUVBLFdBQVMsVUFBVTtBQUNmLGFBQVMsS0FBSyxNQUFNLFNBQVM7QUFDN0IsaUJBQWE7QUFBQSxFQUNqQjtBQUVBLFdBQVMsYUFBYTtBQUNsQixRQUFJLFlBQWE7QUFDYixhQUFPLFVBQVUsVUFBVSxFQUFFO0FBQzdCLGFBQU87QUFBQSxJQUNYO0FBQ0EsV0FBTztBQUFBLEVBQ1g7QUFFQSxXQUFTLFlBQVksR0FBRztBQUNwQixRQUFHLFVBQVUsS0FBSyxXQUFXLEtBQUssU0FBUyxDQUFDLEdBQUc7QUFDM0MsbUJBQWEsQ0FBQyxDQUFDLFlBQVksQ0FBQztBQUFBLElBQ2hDO0FBQUEsRUFDSjtBQUVBLFdBQVMsWUFBWSxHQUFHO0FBRXBCLFdBQU8sRUFBRSxFQUFFLFVBQVUsRUFBRSxPQUFPLGVBQWUsRUFBRSxVQUFVLEVBQUUsT0FBTztBQUFBLEVBQ3RFO0FBRUEsV0FBUyxVQUFVLEdBQUc7QUFDbEIsUUFBSSxlQUFlLEVBQUUsWUFBWSxTQUFZLEVBQUUsVUFBVSxFQUFFO0FBQzNELFFBQUksZUFBZSxHQUFHO0FBQ2xCLGNBQVE7QUFBQSxJQUNaO0FBQUEsRUFDSjtBQUVBLFdBQVMsVUFBVSxTQUFTLGVBQWU7QUFDdkMsYUFBUyxnQkFBZ0IsTUFBTSxTQUFTO0FBQ3hDLGlCQUFhO0FBQUEsRUFDakI7QUFFQSxXQUFTLFlBQVksR0FBRztBQUNwQixpQkFBYSxVQUFVLENBQUM7QUFDeEIsUUFBSSxVQUFVLEtBQUssV0FBVztBQUMxQixtQkFBYSxDQUFDO0FBQUEsSUFDbEI7QUFBQSxFQUNKO0FBRUEsV0FBUyxVQUFVLEdBQUc7QUFDbEIsUUFBSSxlQUFlLEVBQUUsWUFBWSxTQUFZLEVBQUUsVUFBVSxFQUFFO0FBQzNELFFBQUcsY0FBYyxlQUFlLEdBQUc7QUFDL0IsYUFBTyxNQUFNO0FBQ2IsYUFBTztBQUFBLElBQ1g7QUFDQSxXQUFPO0FBQUEsRUFDWDtBQUVBLFdBQVMsYUFBYSxHQUFHO0FBQ3JCLFFBQUkscUJBQXFCLFFBQVEsMkJBQTJCLEtBQUs7QUFDakUsUUFBSSxvQkFBb0IsUUFBUSwwQkFBMEIsS0FBSztBQUcvRCxRQUFJLGNBQWMsUUFBUSxtQkFBbUIsS0FBSztBQUVsRCxRQUFJLGNBQWMsT0FBTyxhQUFhLEVBQUUsVUFBVTtBQUNsRCxRQUFJLGFBQWEsRUFBRSxVQUFVO0FBQzdCLFFBQUksWUFBWSxFQUFFLFVBQVU7QUFDNUIsUUFBSSxlQUFlLE9BQU8sY0FBYyxFQUFFLFVBQVU7QUFHcEQsUUFBSSxjQUFjLE9BQU8sYUFBYSxFQUFFLFVBQVcsb0JBQW9CO0FBQ3ZFLFFBQUksYUFBYSxFQUFFLFVBQVcsb0JBQW9CO0FBQ2xELFFBQUksWUFBWSxFQUFFLFVBQVcscUJBQXFCO0FBQ2xELFFBQUksZUFBZSxPQUFPLGNBQWMsRUFBRSxVQUFXLHFCQUFxQjtBQUcxRSxRQUFJLENBQUMsY0FBYyxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLGVBQWUsUUFBVztBQUN4RixnQkFBVTtBQUFBLElBQ2QsV0FFUyxlQUFlO0FBQWMsZ0JBQVUsV0FBVztBQUFBLGFBQ2xELGNBQWM7QUFBYyxnQkFBVSxXQUFXO0FBQUEsYUFDakQsY0FBYztBQUFXLGdCQUFVLFdBQVc7QUFBQSxhQUM5QyxhQUFhO0FBQWEsZ0JBQVUsV0FBVztBQUFBLGFBQy9DO0FBQVksZ0JBQVUsVUFBVTtBQUFBLGFBQ2hDO0FBQVcsZ0JBQVUsVUFBVTtBQUFBLGFBQy9CO0FBQWMsZ0JBQVUsVUFBVTtBQUFBLGFBQ2xDO0FBQWEsZ0JBQVUsVUFBVTtBQUFBLEVBQzlDOzs7QUM1SEE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBdURBLE1BQU1DLFFBQU8sdUJBQXVCLFlBQVksU0FBUyxFQUFFO0FBRTNELE1BQU0sU0FBUztBQUNmLE1BQU0sYUFBYTtBQUNuQixNQUFNLGFBQWE7QUFNWixXQUFTLFNBQVM7QUFDckIsV0FBT0EsTUFBSyxNQUFNO0FBQUEsRUFDdEI7QUFLTyxXQUFTLGFBQWE7QUFDekIsV0FBT0EsTUFBSyxVQUFVO0FBQUEsRUFDMUI7QUFNTyxXQUFTLGFBQWE7QUFDekIsV0FBT0EsTUFBSyxVQUFVO0FBQUEsRUFDMUI7OztBQ2xGQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsZ0JBQUFDO0FBQUEsSUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsZ0JBQUFDO0FBQUEsSUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFtQkEsTUFBTSxTQUFTO0FBQ2YsTUFBTSxXQUFXO0FBQ2pCLE1BQU0sYUFBYTtBQUNuQixNQUFNLGVBQWU7QUFDckIsTUFBTSxVQUFVO0FBQ2hCLE1BQU0sT0FBTztBQUNiLE1BQU0sYUFBYTtBQUNuQixNQUFNLGFBQWE7QUFDbkIsTUFBTSxpQkFBaUI7QUFDdkIsTUFBTSxzQkFBc0I7QUFDNUIsTUFBTSxtQkFBbUI7QUFDekIsTUFBTSxTQUFTO0FBQ2YsTUFBTSxPQUFPO0FBQ2IsTUFBTSxXQUFXO0FBQ2pCLE1BQU0sYUFBYTtBQUNuQixNQUFNLGlCQUFpQjtBQUN2QixNQUFNLFdBQVc7QUFDakIsTUFBTSxhQUFhO0FBQ25CLE1BQU0sVUFBVTtBQUNoQixNQUFNLE9BQU87QUFDYixNQUFNLFFBQVE7QUFDZCxNQUFNLHNCQUFzQjtBQUM1QixNQUFNQyxnQkFBZTtBQUNyQixNQUFNLFFBQVE7QUFDZCxNQUFNLFNBQVM7QUFDZixNQUFNLFNBQVM7QUFDZixNQUFNLFVBQVU7QUFDaEIsTUFBTSxZQUFZO0FBQ2xCLE1BQU0sZUFBZTtBQUNyQixNQUFNLGVBQWU7QUFFckIsTUFBTSxhQUFhLElBQUksRUFBRTtBQUV6QixXQUFTLGFBQWFDLFFBQU07QUFDeEIsV0FBTztBQUFBLE1BQ0gsS0FBSyxDQUFDLGVBQWUsYUFBYSx1QkFBdUIsWUFBWSxRQUFRLFVBQVUsQ0FBQztBQUFBLE1BQ3hGLFFBQVEsTUFBTUEsT0FBSyxNQUFNO0FBQUEsTUFDekIsVUFBVSxDQUFDLFVBQVVBLE9BQUssVUFBVSxFQUFDLE1BQUssQ0FBQztBQUFBLE1BQzNDLFlBQVksTUFBTUEsT0FBSyxVQUFVO0FBQUEsTUFDakMsY0FBYyxNQUFNQSxPQUFLLFlBQVk7QUFBQSxNQUNyQyxTQUFTLENBQUNDLFFBQU9DLFlBQVdGLE9BQUssU0FBUyxFQUFDLE9BQUFDLFFBQU8sUUFBQUMsUUFBTSxDQUFDO0FBQUEsTUFDekQsTUFBTSxNQUFNRixPQUFLLElBQUk7QUFBQSxNQUNyQixZQUFZLENBQUNDLFFBQU9DLFlBQVdGLE9BQUssWUFBWSxFQUFDLE9BQUFDLFFBQU8sUUFBQUMsUUFBTSxDQUFDO0FBQUEsTUFDL0QsWUFBWSxDQUFDRCxRQUFPQyxZQUFXRixPQUFLLFlBQVksRUFBQyxPQUFBQyxRQUFPLFFBQUFDLFFBQU0sQ0FBQztBQUFBLE1BQy9ELGdCQUFnQixDQUFDLFVBQVVGLE9BQUssZ0JBQWdCLEVBQUMsYUFBYSxNQUFLLENBQUM7QUFBQSxNQUNwRSxxQkFBcUIsQ0FBQyxHQUFHLE1BQU1BLE9BQUsscUJBQXFCLEVBQUMsR0FBRyxFQUFDLENBQUM7QUFBQSxNQUMvRCxrQkFBa0IsTUFBTUEsT0FBSyxnQkFBZ0I7QUFBQSxNQUM3QyxRQUFRLE1BQU1BLE9BQUssTUFBTTtBQUFBLE1BQ3pCLE1BQU0sTUFBTUEsT0FBSyxJQUFJO0FBQUEsTUFDckIsVUFBVSxNQUFNQSxPQUFLLFFBQVE7QUFBQSxNQUM3QixZQUFZLE1BQU1BLE9BQUssVUFBVTtBQUFBLE1BQ2pDLGdCQUFnQixNQUFNQSxPQUFLLGNBQWM7QUFBQSxNQUN6QyxVQUFVLE1BQU1BLE9BQUssUUFBUTtBQUFBLE1BQzdCLFlBQVksTUFBTUEsT0FBSyxVQUFVO0FBQUEsTUFDakMsU0FBUyxNQUFNQSxPQUFLLE9BQU87QUFBQSxNQUMzQixNQUFNLE1BQU1BLE9BQUssSUFBSTtBQUFBLE1BQ3JCLE9BQU8sTUFBTUEsT0FBSyxLQUFLO0FBQUEsTUFDdkIscUJBQXFCLENBQUMsR0FBRyxHQUFHLEdBQUcsTUFBTUEsT0FBSyxxQkFBcUIsRUFBQyxHQUFHLEdBQUcsR0FBRyxFQUFDLENBQUM7QUFBQSxNQUMzRSxjQUFjLENBQUNHLGVBQWNILE9BQUtELGVBQWMsRUFBQyxXQUFBSSxXQUFTLENBQUM7QUFBQSxNQUMzRCxPQUFPLE1BQU1ILE9BQUssS0FBSztBQUFBLE1BQ3ZCLFFBQVEsTUFBTUEsT0FBSyxNQUFNO0FBQUEsTUFDekIsUUFBUSxNQUFNQSxPQUFLLE1BQU07QUFBQSxNQUN6QixTQUFTLE1BQU1BLE9BQUssT0FBTztBQUFBLE1BQzNCLFdBQVcsTUFBTUEsT0FBSyxTQUFTO0FBQUEsTUFDL0IsY0FBYyxNQUFNQSxPQUFLLFlBQVk7QUFBQSxNQUNyQyxjQUFjLENBQUMsY0FBY0EsT0FBSyxjQUFjLEVBQUMsVUFBUyxDQUFDO0FBQUEsSUFDL0Q7QUFBQSxFQUNKO0FBUU8sV0FBUyxJQUFJLFlBQVk7QUFDNUIsV0FBTyxhQUFhLHVCQUF1QixZQUFZLFFBQVEsVUFBVSxDQUFDO0FBQUEsRUFDOUU7QUFLTyxXQUFTLFNBQVM7QUFDckIsZUFBVyxPQUFPO0FBQUEsRUFDdEI7QUFNTyxXQUFTLFNBQVMsT0FBTztBQUM1QixlQUFXLFNBQVMsS0FBSztBQUFBLEVBQzdCO0FBS08sV0FBUyxhQUFhO0FBQ3pCLGVBQVcsV0FBVztBQUFBLEVBQzFCO0FBT08sV0FBUyxRQUFRQyxRQUFPQyxTQUFRO0FBQ25DLGVBQVcsUUFBUUQsUUFBT0MsT0FBTTtBQUFBLEVBQ3BDO0FBS08sV0FBUyxPQUFPO0FBQ25CLFdBQU8sV0FBVyxLQUFLO0FBQUEsRUFDM0I7QUFPTyxXQUFTLFdBQVdELFFBQU9DLFNBQVE7QUFDdEMsZUFBVyxXQUFXRCxRQUFPQyxPQUFNO0FBQUEsRUFDdkM7QUFPTyxXQUFTLFdBQVdELFFBQU9DLFNBQVE7QUFDdEMsZUFBVyxXQUFXRCxRQUFPQyxPQUFNO0FBQUEsRUFDdkM7QUFNTyxXQUFTLGVBQWUsT0FBTztBQUNsQyxlQUFXLGVBQWUsS0FBSztBQUFBLEVBQ25DO0FBT08sV0FBUyxvQkFBb0IsR0FBRyxHQUFHO0FBQ3RDLGVBQVcsb0JBQW9CLEdBQUcsQ0FBQztBQUFBLEVBQ3ZDO0FBS08sV0FBUyxtQkFBbUI7QUFDL0IsV0FBTyxXQUFXLGlCQUFpQjtBQUFBLEVBQ3ZDO0FBS08sV0FBUyxTQUFTO0FBQ3JCLFdBQU8sV0FBVyxPQUFPO0FBQUEsRUFDN0I7QUFLTyxXQUFTRSxRQUFPO0FBQ25CLGVBQVcsS0FBSztBQUFBLEVBQ3BCO0FBS08sV0FBUyxXQUFXO0FBQ3ZCLGVBQVcsU0FBUztBQUFBLEVBQ3hCO0FBS08sV0FBUyxhQUFhO0FBQ3pCLGVBQVcsV0FBVztBQUFBLEVBQzFCO0FBS08sV0FBUyxpQkFBaUI7QUFDN0IsZUFBVyxlQUFlO0FBQUEsRUFDOUI7QUFLTyxXQUFTLFdBQVc7QUFDdkIsZUFBVyxTQUFTO0FBQUEsRUFDeEI7QUFLTyxXQUFTLGFBQWE7QUFDekIsZUFBVyxXQUFXO0FBQUEsRUFDMUI7QUFLTyxXQUFTLFVBQVU7QUFDdEIsZUFBVyxRQUFRO0FBQUEsRUFDdkI7QUFLTyxXQUFTQyxRQUFPO0FBQ25CLGVBQVcsS0FBSztBQUFBLEVBQ3BCO0FBS08sV0FBUyxRQUFRO0FBQ3BCLGVBQVcsTUFBTTtBQUFBLEVBQ3JCO0FBU08sV0FBUyxvQkFBb0IsR0FBRyxHQUFHLEdBQUcsR0FBRztBQUM1QyxlQUFXLG9CQUFvQixHQUFHLEdBQUcsR0FBRyxDQUFDO0FBQUEsRUFDN0M7QUFNTyxXQUFTLGFBQWFGLFlBQVc7QUFDcEMsZUFBVyxhQUFhQSxVQUFTO0FBQUEsRUFDckM7QUFLTyxXQUFTLFFBQVE7QUFDcEIsV0FBTyxXQUFXLE1BQU07QUFBQSxFQUM1QjtBQUtPLFdBQVMsU0FBUztBQUNyQixXQUFPLFdBQVcsT0FBTztBQUFBLEVBQzdCO0FBS08sV0FBUyxTQUFTO0FBQ3JCLGVBQVcsT0FBTztBQUFBLEVBQ3RCO0FBS08sV0FBUyxVQUFVO0FBQ3RCLGVBQVcsUUFBUTtBQUFBLEVBQ3ZCO0FBS08sV0FBUyxZQUFZO0FBQ3hCLGVBQVcsVUFBVTtBQUFBLEVBQ3pCO0FBS08sV0FBUyxlQUFlO0FBQzNCLFdBQU8sV0FBVyxhQUFhO0FBQUEsRUFDbkM7QUFNTyxXQUFTLGFBQWEsV0FBVztBQUNwQyxlQUFXLGFBQWEsU0FBUztBQUFBLEVBQ3JDOzs7QUMzVEE7QUFBQTtBQUFBO0FBQUE7OztBQ0FBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7O0FDQ08sTUFBTSxhQUFhO0FBQUEsSUFDekIsU0FBUztBQUFBLE1BQ1Isb0JBQW9CO0FBQUEsTUFDcEIsc0JBQXNCO0FBQUEsTUFDdEIsWUFBWTtBQUFBLE1BQ1osb0JBQW9CO0FBQUEsTUFDcEIsa0JBQWtCO0FBQUEsTUFDbEIsdUJBQXVCO0FBQUEsTUFDdkIsb0JBQW9CO0FBQUEsTUFDcEIsNEJBQTRCO0FBQUEsTUFDNUIsZ0JBQWdCO0FBQUEsTUFDaEIsY0FBYztBQUFBLE1BQ2QsbUJBQW1CO0FBQUEsTUFDbkIsZ0JBQWdCO0FBQUEsTUFDaEIsa0JBQWtCO0FBQUEsTUFDbEIsa0JBQWtCO0FBQUEsTUFDbEIsb0JBQW9CO0FBQUEsTUFDcEIsZUFBZTtBQUFBLE1BQ2YsZ0JBQWdCO0FBQUEsTUFDaEIsa0JBQWtCO0FBQUEsTUFDbEIsYUFBYTtBQUFBLE1BQ2IsZ0JBQWdCO0FBQUEsTUFDaEIsaUJBQWlCO0FBQUEsTUFDakIsZ0JBQWdCO0FBQUEsTUFDaEIsaUJBQWlCO0FBQUEsTUFDakIsaUJBQWlCO0FBQUEsTUFDakIsZ0JBQWdCO0FBQUEsSUFDakI7QUFBQSxJQUNBLEtBQUs7QUFBQSxNQUNKLDRCQUE0QjtBQUFBLE1BQzVCLHVDQUF1QztBQUFBLE1BQ3ZDLHlDQUF5QztBQUFBLE1BQ3pDLDBCQUEwQjtBQUFBLE1BQzFCLG9DQUFvQztBQUFBLE1BQ3BDLHNDQUFzQztBQUFBLE1BQ3RDLG9DQUFvQztBQUFBLE1BQ3BDLDBDQUEwQztBQUFBLE1BQzFDLCtCQUErQjtBQUFBLE1BQy9CLG9CQUFvQjtBQUFBLE1BQ3BCLHdDQUF3QztBQUFBLE1BQ3hDLHNCQUFzQjtBQUFBLE1BQ3RCLHNCQUFzQjtBQUFBLE1BQ3RCLDZCQUE2QjtBQUFBLE1BQzdCLGdDQUFnQztBQUFBLE1BQ2hDLHFCQUFxQjtBQUFBLE1BQ3JCLDZCQUE2QjtBQUFBLE1BQzdCLDBCQUEwQjtBQUFBLE1BQzFCLHVCQUF1QjtBQUFBLE1BQ3ZCLHVCQUF1QjtBQUFBLE1BQ3ZCLDJCQUEyQjtBQUFBLE1BQzNCLCtCQUErQjtBQUFBLE1BQy9CLG9CQUFvQjtBQUFBLE1BQ3BCLHFCQUFxQjtBQUFBLE1BQ3JCLHFCQUFxQjtBQUFBLE1BQ3JCLHNCQUFzQjtBQUFBLE1BQ3RCLGdDQUFnQztBQUFBLE1BQ2hDLGtDQUFrQztBQUFBLE1BQ2xDLG1DQUFtQztBQUFBLE1BQ25DLG9DQUFvQztBQUFBLE1BQ3BDLCtCQUErQjtBQUFBLE1BQy9CLDZCQUE2QjtBQUFBLE1BQzdCLHVCQUF1QjtBQUFBLE1BQ3ZCLGlDQUFpQztBQUFBLE1BQ2pDLDhCQUE4QjtBQUFBLE1BQzlCLDRCQUE0QjtBQUFBLE1BQzVCLHNDQUFzQztBQUFBLE1BQ3RDLDRCQUE0QjtBQUFBLE1BQzVCLHNCQUFzQjtBQUFBLE1BQ3RCLGtDQUFrQztBQUFBLE1BQ2xDLHNCQUFzQjtBQUFBLE1BQ3RCLHdCQUF3QjtBQUFBLE1BQ3hCLDJCQUEyQjtBQUFBLE1BQzNCLHdCQUF3QjtBQUFBLE1BQ3hCLG1CQUFtQjtBQUFBLE1BQ25CLDBCQUEwQjtBQUFBLE1BQzFCLDhCQUE4QjtBQUFBLE1BQzlCLHlCQUF5QjtBQUFBLE1BQ3pCLDZCQUE2QjtBQUFBLE1BQzdCLGlCQUFpQjtBQUFBLE1BQ2pCLGdCQUFnQjtBQUFBLE1BQ2hCLHNCQUFzQjtBQUFBLE1BQ3RCLGVBQWU7QUFBQSxNQUNmLHlCQUF5QjtBQUFBLE1BQ3pCLHdCQUF3QjtBQUFBLE1BQ3hCLG9CQUFvQjtBQUFBLE1BQ3BCLHFCQUFxQjtBQUFBLE1BQ3JCLGlCQUFpQjtBQUFBLE1BQ2pCLGlCQUFpQjtBQUFBLE1BQ2pCLHNCQUFzQjtBQUFBLE1BQ3RCLG1DQUFtQztBQUFBLE1BQ25DLHFDQUFxQztBQUFBLE1BQ3JDLHVCQUF1QjtBQUFBLE1BQ3ZCLHNCQUFzQjtBQUFBLE1BQ3RCLHdCQUF3QjtBQUFBLE1BQ3hCLDJCQUEyQjtBQUFBLE1BQzNCLG1CQUFtQjtBQUFBLE1BQ25CLHFCQUFxQjtBQUFBLE1BQ3JCLHNCQUFzQjtBQUFBLE1BQ3RCLHNCQUFzQjtBQUFBLE1BQ3RCLDhCQUE4QjtBQUFBLE1BQzlCLGlCQUFpQjtBQUFBLE1BQ2pCLHlCQUF5QjtBQUFBLE1BQ3pCLDJCQUEyQjtBQUFBLE1BQzNCLCtCQUErQjtBQUFBLE1BQy9CLDBCQUEwQjtBQUFBLE1BQzFCLDhCQUE4QjtBQUFBLE1BQzlCLGlCQUFpQjtBQUFBLE1BQ2pCLHVCQUF1QjtBQUFBLE1BQ3ZCLGdCQUFn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VTtBQUN2QixTQUFPLE1BQU0sT0FBTztBQUNwQixTQUFPLE1BQU0sWUFBWTtBQUN6QixTQUFPLE1BQU0sVUFBVTtBQUN2QixTQUFPLE1BQU0sU0FBUztBQUN0QixTQUFPLE1BQU0sUUFBUTtBQUNyQixTQUFPLE1BQU0sVUFBVTtBQUN2QixTQUFPLE1BQU0sU0FBUztBQUN0QixTQUFPLE1BQU0sU0FBUztBQUN0QixTQUFPLE1BQU0sTUFBTTtBQUduQixNQUFJLFVBQVU7QUFDZCxXQUFTLGlCQUFpQixvQkFBb0IsV0FBVztBQUNyRCxjQUFVO0FBQ1YsV0FBTyxPQUFPLE9BQU8scUJBQXFCO0FBQzFDLFFBQUcsTUFBTztBQUNOLGVBQVMsc0JBQXNCO0FBQUEsSUFDbkM7QUFBQSxFQUNKLENBQUM7QUFFRCxXQUFTLFVBQVUsSUFBSTtBQUNuQixRQUFJLFdBQVcsU0FBUyxlQUFlLFlBQVk7QUFDL0MsU0FBRztBQUFBLElBQ1AsT0FBTztBQUNILGVBQVMsaUJBQWlCLG9CQUFvQixFQUFFO0FBQUEsSUFDcEQ7QUFBQSxFQUNKO0FBRUEsWUFBVSxNQUFNO0FBQ1osSUFBSSxPQUFPO0FBQUEsRUFDZixDQUFDOyIsCiAgIm5hbWVzIjogWyJzaXplIiwgImNhbGwiLCAiY2FsbCIsICJjYWxsIiwgImNhbGwiLCAiY2FsbCIsICJIaWRlIiwgIlNob3ciLCAic2V0UmVzaXphYmxlIiwgImNhbGwiLCAid2lkdGgiLCAiaGVpZ2h0IiwgInJlc2l6YWJsZSIsICJIaWRlIiwgIlNob3ciLCAiY2FsbCIsICJldmVudE5hbWUiLCAiRXJyb3IiLCAiY2FsbCIsICJFcnJvciIsICJjYWxsIiwgImdlbmVyYXRlSUQiXQp9Cg== diff --git a/v3/internal/commands/build_assets/runtime/runtime.js b/v3/internal/commands/build_assets/runtime/runtime.js index 2c7d16ed30b..baaccee0402 100644 --- a/v3/internal/commands/build_assets/runtime/runtime.js +++ b/v3/internal/commands/build_assets/runtime/runtime.js @@ -1 +1 @@ -(()=>{var le=Object.defineProperty;var w=(e,i)=>{for(var n in i)le(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var de="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=de[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",l={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9,CancelCall:10},se=f();function d(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,m)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();m(Error(c.statusText))}).then(c=>s(c)).catch(c=>m(c))})}var P=d(l.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=d(l.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>Me,Text:()=>xe});var Q=d(l.Clipboard,""),Ce=0,Se=1;function Me(e){return Q(Ce,{text:e})}function xe(){return Q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=d(l.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=d(l.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var M=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",M=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(M=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function W(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){M=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return M&&i>0?(h("drag"),!1):M}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=d(l.Screens,""),Xe=0,qe=1,Qe=2;function Je(){return k(Xe)}function $e(){return k(qe)}function ei(){return k(Qe)}var H={};w(H,{Center:()=>Oi,Close:()=>qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>Qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,li=6,di=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,Mi=21,xi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(d(l.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(li,{width:i,height:n}),SetMinSize:(i,n)=>e(di,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(Mi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(xi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(d(l.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function qi(){r.Close()}function Qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>ln,WailsEvent:()=>x,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var ln=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var dn=d(l.Events,""),cn=0,u=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},x=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=u.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?u.delete(e.name):u.set(e.name,i))}}function _(e,i,n){let o=u.get(e)||[],t=new V(e,i,n);return o.push(t),u.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=u.get(i).filter(o=>o!==e);n.length===0?u.delete(i):u.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>u.delete(o))}function gn(){u.clear()}function Z(e){return dn(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,Mn=5,xn=d(l.Dialog,""),g=new Map;function An(){let e;do e=f();while(g.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{g.set(n,{resolve:o,reject:t}),xn(e,i).catch(a=>{t(a),g.delete(n)})})}function vn(e,i,n){let o=g.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),g.delete(e))}function bn(e,i){let n=g.get(e);n&&(n.reject(i),g.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(Mn,e);function oe(e,i=null){let n=new x(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(m){m!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>_n,ByName:()=>Vn,Call:()=>Hn,Plugin:()=>Zn});window._wails=window._wails||{};window._wails.callResultHandler=kn;window._wails.callErrorHandler=Nn;var y=0,Fn=d(l.Call,""),Ln=d(l.CancelCall,""),v=new Map;function zn(){let e;do e=f();while(v.has(e));return e}function kn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function Nn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){let n=zn(),o=()=>{Ln(e,{"call-id":n})};var t=!1,a=!1,s=new Promise((m,c)=>{i["call-id"]=n,v.set(n,{resolve:m,reject:c}),Fn(e,i).then(p=>{a=!0,t&&o()}).catch(p=>{c(p),v.delete(n)})});return s.cancel=()=>{a?o():t=!0},s}function Hn(e){return O(y,e)}function Vn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function _n(e,...i){return O(y,{methodID:e,args:i})}function Zn(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function jn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}jn(()=>{Y()});})(); +(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return q(Ce,{text:e})}function Me(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/internal/runtime/Taskfile.yaml b/v3/internal/runtime/Taskfile.yaml index 875375d1cd4..794769b2856 100644 --- a/v3/internal/runtime/Taskfile.yaml +++ b/v3/internal/runtime/Taskfile.yaml @@ -38,8 +38,10 @@ tasks: - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/binding/assets/runtime.js - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/frameless/assets/runtime.js - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/window-api/assets/runtime.js + - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/contextmenus/assets/runtime.js - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/wml/assets/runtime.js - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../internal/commands/build_assets/runtime/runtime.js + - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/screen/assets/runtime.js - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../pkg/application/assets/alpha/runtime.js - cmd: echo "Build Complete." diff --git a/v3/pkg/application/assets/alpha/runtime.js b/v3/pkg/application/assets/alpha/runtime.js index 2c7d16ed30b..baaccee0402 100644 --- a/v3/pkg/application/assets/alpha/runtime.js +++ b/v3/pkg/application/assets/alpha/runtime.js @@ -1 +1 @@ -(()=>{var le=Object.defineProperty;var w=(e,i)=>{for(var n in i)le(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var de="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=de[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",l={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9,CancelCall:10},se=f();function d(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,m)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();m(Error(c.statusText))}).then(c=>s(c)).catch(c=>m(c))})}var P=d(l.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=d(l.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>Me,Text:()=>xe});var Q=d(l.Clipboard,""),Ce=0,Se=1;function Me(e){return Q(Ce,{text:e})}function xe(){return Q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=d(l.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=d(l.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var M=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",M=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(M=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function W(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){M=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return M&&i>0?(h("drag"),!1):M}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=d(l.Screens,""),Xe=0,qe=1,Qe=2;function Je(){return k(Xe)}function $e(){return k(qe)}function ei(){return k(Qe)}var H={};w(H,{Center:()=>Oi,Close:()=>qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>Qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,li=6,di=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,Mi=21,xi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(d(l.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(li,{width:i,height:n}),SetMinSize:(i,n)=>e(di,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(Mi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(xi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(d(l.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function qi(){r.Close()}function Qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>ln,WailsEvent:()=>x,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var ln=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var dn=d(l.Events,""),cn=0,u=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},x=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=u.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?u.delete(e.name):u.set(e.name,i))}}function _(e,i,n){let o=u.get(e)||[],t=new V(e,i,n);return o.push(t),u.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=u.get(i).filter(o=>o!==e);n.length===0?u.delete(i):u.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>u.delete(o))}function gn(){u.clear()}function Z(e){return dn(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,Mn=5,xn=d(l.Dialog,""),g=new Map;function An(){let e;do e=f();while(g.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{g.set(n,{resolve:o,reject:t}),xn(e,i).catch(a=>{t(a),g.delete(n)})})}function vn(e,i,n){let o=g.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),g.delete(e))}function bn(e,i){let n=g.get(e);n&&(n.reject(i),g.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(Mn,e);function oe(e,i=null){let n=new x(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(m){m!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>_n,ByName:()=>Vn,Call:()=>Hn,Plugin:()=>Zn});window._wails=window._wails||{};window._wails.callResultHandler=kn;window._wails.callErrorHandler=Nn;var y=0,Fn=d(l.Call,""),Ln=d(l.CancelCall,""),v=new Map;function zn(){let e;do e=f();while(v.has(e));return e}function kn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function Nn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){let n=zn(),o=()=>{Ln(e,{"call-id":n})};var t=!1,a=!1,s=new Promise((m,c)=>{i["call-id"]=n,v.set(n,{resolve:m,reject:c}),Fn(e,i).then(p=>{a=!0,t&&o()}).catch(p=>{c(p),v.delete(n)})});return s.cancel=()=>{a?o():t=!0},s}function Hn(e){return O(y,e)}function Vn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function _n(e,...i){return O(y,{methodID:e,args:i})}function Zn(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function jn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}jn(()=>{Y()});})(); +(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return q(Ce,{text:e})}function Me(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); From a7fb568aff4887337c075aaaec437e49a1a382e2 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 26 Feb 2024 21:39:01 +1100 Subject: [PATCH 076/369] Fix signal handlers --- v3/pkg/application/application_linux.go | 2 + v3/pkg/application/linux_cgo.go | 59 +++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index 3029b96fb97..90c130b77c5 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -176,6 +176,8 @@ func (a *linuxApp) monitorThemeChanges() { } func newPlatformApp(parent *App) *linuxApp { + + C.install_signal_handlers() name := strings.ToLower(strings.Replace(parent.options.Name, " ", "", -1)) if name == "" { name = "undefined" diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 2c4650764e3..ace51e28d30 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -145,6 +145,65 @@ typedef struct Screen { bool isPrimary; } Screen; +// CREDIT: https://github.com/rainycape/magick +#include +#include +#include +#include + +static void fix_signal(int signum) { + struct sigaction st; + + if (sigaction(signum, NULL, &st) < 0) { + goto fix_signal_error; + } + st.sa_flags |= SA_ONSTACK; + if (sigaction(signum, &st, NULL) < 0) { + goto fix_signal_error; + } + return; +fix_signal_error: + fprintf(stderr, "error fixing handler for signal %d, please " + "report this issue to " + "https://github.com/wailsapp/wails: %s\n", + signum, strerror(errno)); +} + +static void install_signal_handlers() { + #if defined(SIGCHLD) + fix_signal(SIGCHLD); + #endif + #if defined(SIGHUP) + fix_signal(SIGHUP); + #endif + #if defined(SIGINT) + fix_signal(SIGINT); + #endif + #if defined(SIGQUIT) + fix_signal(SIGQUIT); + #endif + #if defined(SIGABRT) + fix_signal(SIGABRT); + #endif + #if defined(SIGFPE) + fix_signal(SIGFPE); + #endif + #if defined(SIGTERM) + fix_signal(SIGTERM); + #endif + #if defined(SIGBUS) + fix_signal(SIGBUS); + #endif + #if defined(SIGSEGV) + fix_signal(SIGSEGV); + #endif + #if defined(SIGXCPU) + fix_signal(SIGXCPU); + #endif + #if defined(SIGXFSZ) + fix_signal(SIGXFSZ); + #endif +} static int GetNumScreens(){ return 0; From 6d90c1678c31039d7d5a3e36381c31ca54b00623 Mon Sep 17 00:00:00 2001 From: Travis McLane Date: Mon, 26 Feb 2024 09:21:47 -0600 Subject: [PATCH 077/369] move install_signal_handlers to proper location --- v3/pkg/application/application_linux.go | 1 - v3/pkg/application/linux_cgo.go | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index 90c130b77c5..4db23d058c1 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -177,7 +177,6 @@ func (a *linuxApp) monitorThemeChanges() { func newPlatformApp(parent *App) *linuxApp { - C.install_signal_handlers() name := strings.ToLower(strings.Replace(parent.options.Name, " ", "", -1)) if name == "" { name = "undefined" diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index ace51e28d30..911cf6c4721 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -4,12 +4,13 @@ package application import ( "fmt" - "github.com/wailsapp/wails/v3/internal/assetserver/webview" "regexp" "strings" "sync" "unsafe" + "github.com/wailsapp/wails/v3/internal/assetserver/webview" + "github.com/wailsapp/wails/v3/pkg/events" ) @@ -317,6 +318,8 @@ func appName() string { } func appNew(name string) pointer { + C.install_signal_handlers() + // prevent leading number if matched, _ := regexp.MatchString(`^\d+`, name); matched { name = fmt.Sprintf("_%s", name) From 0fde6c9922b7ce2377902430dddf6c9f7411737e Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 2 Mar 2024 17:34:46 +1100 Subject: [PATCH 078/369] Latest status --- mkdocs-website/shared/alpha5.csv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mkdocs-website/shared/alpha5.csv b/mkdocs-website/shared/alpha5.csv index 158b6a0c7cf..f62050de27f 100644 --- a/mkdocs-website/shared/alpha5.csv +++ b/mkdocs-website/shared/alpha5.csv @@ -1,9 +1,9 @@ Example,Linux binding," " -build," " +build,:material-check-bold: clipboard,:material-check-bold: -context menus," " -dialogs," " +context menus,:material-minus: +dialogs,:material-minus: drag-n-drop," " events,:material-check-bold: frameless,:material-check-bold: From c21784037d1554bbe3f794f3d5af4fc99f6f8346 Mon Sep 17 00:00:00 2001 From: Travis McLane Date: Wed, 6 Mar 2024 16:49:18 -0600 Subject: [PATCH 079/369] wip: fixing rebase issue --- v3/pkg/application/linux_cgo.go | 27 ---------------------- v3/pkg/application/webview_window_linux.go | 3 --- 2 files changed, 30 deletions(-) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 911cf6c4721..631048beabc 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -1186,33 +1186,6 @@ func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventT C.signal_connect(unsafe.Pointer(webview), c.String("key-press-event"), C.onKeyPressEvent, winID) } -//export handleLoadChanged -func handleLoadChanged(webview *C.WebKitWebView, event C.WebKitLoadEvent, data C.uintptr_t) { - switch event { - case C.WEBKIT_LOAD_FINISHED: - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowLoadChanged)) - } -} - -func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventType)) { - - c := NewCalloc() - defer c.Free() - - winID := unsafe.Pointer(uintptr(C.uint(w.parent.ID()))) - - // Set up the window close event - wv := unsafe.Pointer(w.webview) - C.signal_connect(unsafe.Pointer(w.window), c.String("delete-event"), C.handleDeleteEvent, winID) - C.signal_connect(wv, c.String("load-changed"), C.handleLoadChanged, winID) - - contentManager := C.webkit_web_view_get_user_content_manager(w.webKitWebView()) - C.signal_connect(unsafe.Pointer(contentManager), c.String("script-message-received::external"), C.sendMessageToBackend, nil) - C.signal_connect(wv, c.String("button-press-event"), C.onButtonEvent, winID) - C.signal_connect(wv, c.String("button-release-event"), C.onButtonEvent, winID) - C.signal_connect(wv, c.String("key-press-event"), C.onKeyPressEvent, winID) -} - func getMouseButtons() (bool, bool, bool) { var pointer *C.GdkDevice var state C.GdkModifierType diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 5dd82f79132..628afcaf221 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -5,9 +5,6 @@ package application import "C" import ( "fmt" - "math" - - "math" "github.com/wailsapp/wails/v3/internal/assetserver" "github.com/wailsapp/wails/v3/internal/capabilities" From 716f4af808f3df732946606101878b9e132bceea Mon Sep 17 00:00:00 2001 From: Travis McLane Date: Wed, 6 Mar 2024 17:10:41 -0600 Subject: [PATCH 080/369] [linux] add missing implementations --- v3/pkg/application/linux_cgo.go | 10 +++++++--- v3/pkg/application/webview_window_linux.go | 12 ++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 631048beabc..17a992a7556 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -1100,6 +1100,10 @@ func (w *linuxWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) { C.gtk_window_set_keep_above(w.gtkWindow(), gtkBool(alwaysOnTop)) } +func (w *linuxWebviewWindow) flash(_ bool) { + // Not supported on Linux +} + func (w *linuxWebviewWindow) setTitle(title string) { if !w.parent.options.Frameless { cTitle := C.CString(title) @@ -1181,9 +1185,9 @@ func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventT contentManager := C.webkit_web_view_get_user_content_manager(w.webKitWebView()) C.signal_connect(unsafe.Pointer(contentManager), c.String("script-message-received::external"), C.sendMessageToBackend, nil) - C.signal_connect(unsafe.Pointer(webview), c.String("button-press-event"), C.onButtonEvent, winID) - C.signal_connect(unsafe.Pointer(webview), c.String("button-release-event"), C.onButtonEvent, winID) - C.signal_connect(unsafe.Pointer(webview), c.String("key-press-event"), C.onKeyPressEvent, winID) + C.signal_connect(unsafe.Pointer(w.webview), c.String("button-press-event"), C.onButtonEvent, winID) + C.signal_connect(unsafe.Pointer(w.webview), c.String("button-release-event"), C.onButtonEvent, winID) + C.signal_connect(unsafe.Pointer(w.webview), c.String("key-press-event"), C.onKeyPressEvent, winID) } func getMouseButtons() (bool, bool, bool) { diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 628afcaf221..a1a171e1b6e 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -75,10 +75,22 @@ func (w *linuxWebviewWindow) isNormal() bool { return !w.isMinimised() && !w.isMaximised() && !w.isFullscreen() } +func (w *linuxWebviewWindow) setCloseButtonEnabled(enabled bool) { + // C.enableCloseButton(w.nsWindow, C.bool(enabled)) +} + func (w *linuxWebviewWindow) setFullscreenButtonEnabled(enabled bool) { // Not implemented } +func (w *linuxWebviewWindow) setMinimiseButtonEnabled(enabled bool) { + //C.enableMinimiseButton(w.nsWindow, C.bool(enabled)) +} + +func (w *linuxWebviewWindow) setMaximiseButtonEnabled(enabled bool) { + //C.enableMaximiseButton(w.nsWindow, C.bool(enabled)) +} + func (w *linuxWebviewWindow) disableSizeConstraints() { x, y, width, height, scale := w.getCurrentMonitorGeometry() w.setMinMaxSize(x, y, width*scale, height*scale) From eedd5eb7d24037ce384bf2bfda279f788d6f9672 Mon Sep 17 00:00:00 2001 From: Travis McLane Date: Thu, 7 Mar 2024 09:02:39 -0600 Subject: [PATCH 081/369] reuse the 'wv' variable --- v3/pkg/application/linux_cgo.go | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 17a992a7556..a7ce902ae49 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -1185,9 +1185,9 @@ func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventT contentManager := C.webkit_web_view_get_user_content_manager(w.webKitWebView()) C.signal_connect(unsafe.Pointer(contentManager), c.String("script-message-received::external"), C.sendMessageToBackend, nil) - C.signal_connect(unsafe.Pointer(w.webview), c.String("button-press-event"), C.onButtonEvent, winID) - C.signal_connect(unsafe.Pointer(w.webview), c.String("button-release-event"), C.onButtonEvent, winID) - C.signal_connect(unsafe.Pointer(w.webview), c.String("key-press-event"), C.onKeyPressEvent, winID) + C.signal_connect(wv, c.String("button-press-event"), C.onButtonEvent, winID) + C.signal_connect(wv, c.String("button-release-event"), C.onButtonEvent, winID) + C.signal_connect(wv, c.String("key-press-event"), C.onKeyPressEvent, winID) } func getMouseButtons() (bool, bool, bool) { @@ -1347,15 +1347,13 @@ func onDragNDrop(target unsafe.Pointer, context *C.GdkDragContext, x C.gint, y C //export onKeyPressEvent func onKeyPressEvent(widget *C.GtkWidget, event *C.GdkEventKey, userData C.uintptr_t) C.gboolean { windowID := uint(C.uint(userData)) - accelerator, ok := getKeyboardState(event) - if !ok { - return C.gboolean(1) - } - windowKeyEvents <- &windowKeyEvent{ - windowId: windowID, - acceleratorString: accelerator, + if accelerator, ok := getKeyboardState(event); ok { + windowKeyEvents <- &windowKeyEvent{ + windowId: windowID, + acceleratorString: accelerator, + } } - return C.gboolean(1) + return C.gboolean(0) } func getKeyboardState(event *C.GdkEventKey) (string, bool) { From fb46cce9631e9b45de3c0e36949ecd9212636472 Mon Sep 17 00:00:00 2001 From: Travis McLane Date: Thu, 7 Mar 2024 09:03:32 -0600 Subject: [PATCH 082/369] simplify key handling logic --- v3/pkg/application/linux_cgo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index a7ce902ae49..96e130d04e1 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -1353,7 +1353,7 @@ func onKeyPressEvent(widget *C.GtkWidget, event *C.GdkEventKey, userData C.uintp acceleratorString: accelerator, } } - return C.gboolean(0) + return C.gboolean(1) } func getKeyboardState(event *C.GdkEventKey) (string, bool) { From 4b2189ba51973b74ad5c2d3b620909bb65b945b8 Mon Sep 17 00:00:00 2001 From: Travis McLane Date: Thu, 7 Mar 2024 09:03:47 -0600 Subject: [PATCH 083/369] allow keypress propagation - this allows the webkit to add values to the `input` when typed FIXME: does this need to be configurable? --- v3/pkg/application/linux_cgo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index 96e130d04e1..a7ce902ae49 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -1353,7 +1353,7 @@ func onKeyPressEvent(widget *C.GtkWidget, event *C.GdkEventKey, userData C.uintp acceleratorString: accelerator, } } - return C.gboolean(1) + return C.gboolean(0) } func getKeyboardState(event *C.GdkEventKey) (string, bool) { From f38532bcf5be446ebbf2b68498bb4521975b10fc Mon Sep 17 00:00:00 2001 From: Josh Drake Date: Fri, 8 Mar 2024 01:06:14 -0600 Subject: [PATCH 084/369] Correctly compute 'startURL' when using a frontend development server. (#3299) * Fix computing 'startURL' when 'FRONTEND_DEVSERVER_URL' is present. * Respect provided URL when computing 'startURL' and 'FRONTEND_DEVSERVER_URL' is present. * Update changelog. * Correctly produce absolute URI in 'GetStartURL' when input is provided. --- mkdocs-website/docs/en/changelog.md | 1 + v3/internal/assetserver/assetserver.go | 27 ++++++++++---------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/mkdocs-website/docs/en/changelog.md b/mkdocs-website/docs/en/changelog.md index fa3a3f83826..ade4892108d 100644 --- a/mkdocs-website/docs/en/changelog.md +++ b/mkdocs-website/docs/en/changelog.md @@ -43,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix failing Windows build due to unknown option by [thomas-senechal](https://github.com/thomas-senechal) in PR [#3208](https://github.com/wailsapp/wails/pull/3208) - Fix wrong baseURL when open window twice by @5aaee9 in PR [#3273](https://github.com/wailsapp/wails/pull/3273) - Fix ordering of if branches in `WebviewWindow.Restore` method by [@fbbdev](https://github.com/fbbdev) in [#3279](https://github.com/wailsapp/wails/pull/3279) +- Correctly compute `startURL` across multiple `GetStartURL` invocations when `FRONTEND_DEVSERVER_URL` is present. [#3299](https://github.com/wailsapp/wails/pull/3299) ### Changed diff --git a/v3/internal/assetserver/assetserver.go b/v3/internal/assetserver/assetserver.go index 0d80007e763..24b0492242a 100644 --- a/v3/internal/assetserver/assetserver.go +++ b/v3/internal/assetserver/assetserver.go @@ -148,26 +148,19 @@ func GetStartURL(userURL string) (string, error) { } port := parsedURL.Port() if port != "" { - baseURL.Host = net.JoinHostPort(baseURL.Host, port) + baseURL.Host = net.JoinHostPort(baseURL.Hostname(), port) startURL = baseURL.String() } - } else { - if userURL != "" { - // parse the url - parsedURL, err := url.Parse(userURL) - if err != nil { - return "", fmt.Errorf("Error parsing URL: " + err.Error()) - } - if parsedURL.Scheme == "" { - startURL = baseURL.ResolveReference(&url.URL{Path: userURL}).String() - // if the original URL had a trailing slash, add it back - if strings.HasSuffix(userURL, "/") && !strings.HasSuffix(startURL, "/") { - startURL = startURL + "/" - } - } else { - startURL = userURL - } + } + + if userURL != "" { + parsedURL, err := baseURL.Parse(userURL) + if err != nil { + return "", fmt.Errorf("Error parsing URL: " + err.Error()) } + + startURL = parsedURL.String() } + return startURL, nil } From e4fd7df68bc53fed083dbfd1eb40f96451061a5a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 20:12:17 +1100 Subject: [PATCH 085/369] chore: update sponsors.svg (#3302) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index fc6897ba73d..d73af96b637 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -17,16 +17,20 @@ text { } Bronze Sponsors
- Cody Bentley - + Cody Bentley + - Kazuya Gokita - + Kazuya Gokita + - Simon Thomas - + Simon Thomas + + + + CodeRabbit + Covering Costs Nick @@ -125,46 +129,42 @@ text { Helpers - + - + - + - - - - - + - + - + - + - + - + - + From e6805707d8f35ca19c5fc6f9a53198c75c227ed9 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 14 Mar 2024 08:52:10 +1100 Subject: [PATCH 086/369] Fix mac compilation issues --- v3/go.mod | 14 +++++----- v3/go.sum | 27 +++++++------------ v3/pkg/application/webview_window_darwin.go | 10 +++---- .../application/webview_window_darwin_dev.go | 2 +- 4 files changed, 20 insertions(+), 33 deletions(-) diff --git a/v3/go.mod b/v3/go.mod index 0eade4d33a4..62cbfc35424 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -1,8 +1,6 @@ module github.com/wailsapp/wails/v3 -go 1.21.1 - -toolchain go1.21.4 +go 1.22 require ( github.com/atterpac/refresh v0.5.11 @@ -36,7 +34,7 @@ require ( github.com/tc-hib/winres v0.1.6 github.com/wailsapp/go-webview2 v1.0.9 github.com/wailsapp/mimetype v1.4.1 - golang.org/x/sys v0.17.0 + golang.org/x/sys v0.18.0 modernc.org/sqlite v1.21.0 ) @@ -50,7 +48,7 @@ require ( github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/StackExchange/wmi v1.2.1 // indirect github.com/alexbrainman/ps v0.0.0-20171229230509-b3e1b4a15894 // indirect - github.com/cloudflare/circl v1.3.3 // indirect + github.com/cloudflare/circl v1.3.7 // indirect github.com/containerd/console v1.0.3 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/dustin/go-humanize v1.0.0 // indirect @@ -90,14 +88,14 @@ require ( github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect - golang.org/x/crypto v0.19.0 // indirect + golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/image v0.15.0 // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.19.0 // indirect + golang.org/x/net v0.21.0 // indirect golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect golang.org/x/sync v0.4.0 // indirect - golang.org/x/term v0.17.0 // indirect + golang.org/x/term v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.13.0 // indirect google.golang.org/appengine v1.6.6 // indirect diff --git a/v3/go.sum b/v3/go.sum index 527c3bb67dc..7a60346f0b0 100644 --- a/v3/go.sum +++ b/v3/go.sum @@ -79,8 +79,9 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= @@ -388,10 +389,8 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -408,8 +407,6 @@ golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMx golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= -golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -468,8 +465,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -536,10 +533,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -547,10 +542,8 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/v3/pkg/application/webview_window_darwin.go b/v3/pkg/application/webview_window_darwin.go index 86046f88807..f6ba3038237 100644 --- a/v3/pkg/application/webview_window_darwin.go +++ b/v3/pkg/application/webview_window_darwin.go @@ -904,10 +904,6 @@ func (w *macosWebviewWindow) zoomReset() { C.windowZoomReset(w.nsWindow) } -func (w *macosWebviewWindow) openDevTools() { - openDevTools(w.nsWindow) -} - func (w *macosWebviewWindow) reload() { //TODO: Implement globalApplication.debug("reload called on WebviewWindow", "parentID", w.parent.id) @@ -1132,13 +1128,13 @@ func (w *macosWebviewWindow) run() { } if macOptions.DisableMinimiseButton { - w.setMinimiseButtonEnabled(w.nsWindow, false) + w.setMinimiseButtonEnabled(false) } if macOptions.DisableMaximiseButton { - w.setMaximiseButtonEnabled(w.nsWindow, false) + w.setMaximiseButtonEnabled(false) } if macOptions.DisableCloseButton { - w.enableCloseButton(w.nsWindow, false) + w.setCloseButtonEnabled(false) } if options.IgnoreMouseEvents { diff --git a/v3/pkg/application/webview_window_darwin_dev.go b/v3/pkg/application/webview_window_darwin_dev.go index 41ddfcd0cf1..c16746239ad 100644 --- a/v3/pkg/application/webview_window_darwin_dev.go +++ b/v3/pkg/application/webview_window_darwin_dev.go @@ -49,7 +49,7 @@ void windowEnableDevTools(void* nsWindow) { import "C" func (w *macosWebviewWindow) openDevTools() { - openDevTools(w.nsWindow) + C.openDevTools(w.nsWindow) } func (w *macosWebviewWindow) enableDevTools() { From 8d234cc8429dbb7910d1d3cd5045ab2029e2ac42 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Thu, 14 Mar 2024 08:57:10 +1100 Subject: [PATCH 087/369] Update execjs signature --- v3/pkg/application/webview_window.go | 6 +++--- v3/pkg/application/window.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/v3/pkg/application/webview_window.go b/v3/pkg/application/webview_window.go index a8937505f19..5503c29b744 100644 --- a/v3/pkg/application/webview_window.go +++ b/v3/pkg/application/webview_window.go @@ -500,7 +500,7 @@ func (w *WebviewWindow) SetMaxSize(maxWidth, maxHeight int) Window { } // ExecJS executes the given javascript in the context of the window. -func (w *WebviewWindow) ExecJS(_callID, js string) { +func (w *WebviewWindow) ExecJS(js string) { if w.impl == nil && !w.isDestroyed() { return } @@ -657,7 +657,7 @@ func (w *WebviewWindow) HandleMessage(message string) { w.runtimeLoaded = true w.SetResizable(!w.options.DisableResize) for _, js := range w.pendingJS { - w.ExecJS("", js) + w.ExecJS(js) } } } @@ -1042,7 +1042,7 @@ func (w *WebviewWindow) SetFrameless(frameless bool) Window { func (w *WebviewWindow) DispatchWailsEvent(event *WailsEvent) { msg := fmt.Sprintf("_wails.dispatchWailsEvent(%s);", event.ToJSON()) - w.ExecJS("", msg) + w.ExecJS(msg) } func (w *WebviewWindow) dispatchWindowEvent(id uint) { diff --git a/v3/pkg/application/window.go b/v3/pkg/application/window.go index ce807944417..303a23df0ab 100644 --- a/v3/pkg/application/window.go +++ b/v3/pkg/application/window.go @@ -21,7 +21,7 @@ type Window interface { DispatchWailsEvent(event *WailsEvent) EnableSizeConstraints() Error(message string, args ...any) - ExecJS(callID, js string) + ExecJS(js string) Focus() ForceReload() Fullscreen() Window From 126f17a266fb2eff1f3d44d0497a90034d63feb6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 19:25:49 +1100 Subject: [PATCH 088/369] chore: update sponsors.svg (#3316) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index d73af96b637..0c9f2bddc03 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -32,28 +32,32 @@ text { CodeRabbit Covering Costs - Nick - + Nick + - Marcus - + Marcus + - John - + John + - Matt Holt - + Matt Holt + - Iain - + Iain + - Julien - + Julien + + + + Andrei + Buying Breakfast tc-hib From 209e097ba6c3227adf4f23df440a2416dcc73f0d Mon Sep 17 00:00:00 2001 From: Travis McLane Date: Thu, 14 Mar 2024 13:24:49 -0500 Subject: [PATCH 089/369] rename linux options file `linux` suffix means it won't compile on non-Linux platforms. Shorten the name to avoid: ../../pkg/application/options_webview_window.go:104:8: undefined: LinuxWindow ../../pkg/application/options_application.go:28:8: undefined: LinuxOptions ../../pkg/application/options_webview_window.go:104:8: undefined: LinuxWindow --- .../{options_application_linux.go => options_application_lin.go} | 0 v3/pkg/application/{options_linux.go => options_lin.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename v3/pkg/application/{options_application_linux.go => options_application_lin.go} (100%) rename v3/pkg/application/{options_linux.go => options_lin.go} (100%) diff --git a/v3/pkg/application/options_application_linux.go b/v3/pkg/application/options_application_lin.go similarity index 100% rename from v3/pkg/application/options_application_linux.go rename to v3/pkg/application/options_application_lin.go diff --git a/v3/pkg/application/options_linux.go b/v3/pkg/application/options_lin.go similarity index 100% rename from v3/pkg/application/options_linux.go rename to v3/pkg/application/options_lin.go From f2c4ada1e2797a2b9aadb78bc483b6cf2397c398 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 16 Mar 2024 19:36:21 +1100 Subject: [PATCH 090/369] chore: update sponsors.svg (#3318) Co-authored-by: leaanthony --- website/static/img/sponsors.svg | 36 ++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/website/static/img/sponsors.svg b/website/static/img/sponsors.svg index 0c9f2bddc03..9694ec314c8 100644 --- a/website/static/img/sponsors.svg +++ b/website/static/img/sponsors.svg @@ -59,28 +59,32 @@ text { Andrei Buying Breakfast - tc-hib - + tc-hib + - Tai Groot - + Tai Groot + - Tom Wu - + Tom Wu + - Bironou - + Bironou + - Arden - + Arden + - igops - + igops + + + + vaaski + Buying Coffee @@ -126,11 +130,15 @@ text { - + - + + + + + Helpers From e9a9420e5c5d71faf1d0e7c09feba3c38ec640f9 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 17 Mar 2024 09:42:27 +1100 Subject: [PATCH 091/369] Refactor options. Update deps --- ..._application.go => application_options.go} | 53 ++ v3/pkg/application/options_application_lin.go | 7 - v3/pkg/application/options_application_mac.go | 22 - v3/pkg/application/options_application_win.go | 21 - v3/pkg/application/options_lin.go | 43 -- v3/pkg/application/options_mac.go | 165 ------ v3/pkg/application/options_webview_window.go | 164 ------ .../application/options_webview_window_win.go | 154 ----- v3/pkg/application/webview_window_options.go | 525 ++++++++++++++++++ 9 files changed, 578 insertions(+), 576 deletions(-) rename v3/pkg/application/{options_application.go => application_options.go} (63%) delete mode 100644 v3/pkg/application/options_application_lin.go delete mode 100644 v3/pkg/application/options_application_mac.go delete mode 100644 v3/pkg/application/options_application_win.go delete mode 100644 v3/pkg/application/options_lin.go delete mode 100644 v3/pkg/application/options_mac.go delete mode 100644 v3/pkg/application/options_webview_window.go delete mode 100644 v3/pkg/application/options_webview_window_win.go create mode 100644 v3/pkg/application/webview_window_options.go diff --git a/v3/pkg/application/options_application.go b/v3/pkg/application/application_options.go similarity index 63% rename from v3/pkg/application/options_application.go rename to v3/pkg/application/application_options.go index b60dfd85f7e..e786c66a541 100644 --- a/v3/pkg/application/options_application.go +++ b/v3/pkg/application/application_options.go @@ -114,3 +114,56 @@ func ChainMiddleware(middleware ...Middleware) Middleware { func AssetFileServerFS(assets fs.FS) http.Handler { return assetserver.NewAssetFileServer(assets) } + +/******** Mac Options ********/ + +// ActivationPolicy is the activation policy for the application. +type ActivationPolicy int + +const ( + // ActivationPolicyRegular is used for applications that have a user interface, + ActivationPolicyRegular ActivationPolicy = iota + // ActivationPolicyAccessory is used for applications that do not have a main window, + // such as system tray applications or background applications. + ActivationPolicyAccessory + ActivationPolicyProhibited +) + +// MacOptions contains options for macOS applications. +type MacOptions struct { + // ActivationPolicy is the activation policy for the application. Defaults to + // applicationActivationPolicyRegular. + ActivationPolicy ActivationPolicy + // If set to true, the application will terminate when the last window is closed. + ApplicationShouldTerminateAfterLastWindowClosed bool +} + +/****** Windows Options *******/ + +// WindowsOptions contains options for Windows applications. +type WindowsOptions struct { + + // WndProcInterceptor is a function that will be called for every message sent in the application. + // Use this to hook into the main message loop. This is useful for handling custom window messages. + // If `shouldReturn` is `true` then `returnCode` will be returned by the main message loop. + // If `shouldReturn` is `false` then returnCode will be ignored and the message will be processed by the main message loop. + WndProcInterceptor func(hwnd uintptr, msg uint32, wParam, lParam uintptr) (returnCode uintptr, shouldReturn bool) + + // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. + DisableQuitOnLastWindowClosed bool + + // Path where the WebView2 stores the user data. If empty %APPDATA%\[BinaryName.exe] will be used. + // If the path is not valid, a messagebox will be displayed with the error and the app will exit with error code. + WebviewUserDataPath string + + // Path to the directory with WebView2 executables. If empty WebView2 installed in the system will be used. + WebviewBrowserPath string +} + +/********* Linux Options *********/ + +// LinuxOptions contains options for Linux applications. +type LinuxOptions struct { + // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. + DisableQuitOnLastWindowClosed bool +} diff --git a/v3/pkg/application/options_application_lin.go b/v3/pkg/application/options_application_lin.go deleted file mode 100644 index 8c3741ca67d..00000000000 --- a/v3/pkg/application/options_application_lin.go +++ /dev/null @@ -1,7 +0,0 @@ -package application - -// LinuxOptions contains options for Linux applications. -type LinuxOptions struct { - // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. - DisableQuitOnLastWindowClosed bool -} diff --git a/v3/pkg/application/options_application_mac.go b/v3/pkg/application/options_application_mac.go deleted file mode 100644 index ddfbc80e65b..00000000000 --- a/v3/pkg/application/options_application_mac.go +++ /dev/null @@ -1,22 +0,0 @@ -package application - -// ActivationPolicy is the activation policy for the application. -type ActivationPolicy int - -const ( - // ActivationPolicyRegular is used for applications that have a user interface, - ActivationPolicyRegular ActivationPolicy = iota - // ActivationPolicyAccessory is used for applications that do not have a main window, - // such as system tray applications or background applications. - ActivationPolicyAccessory - ActivationPolicyProhibited -) - -// MacOptions contains options for macOS applications. -type MacOptions struct { - // ActivationPolicy is the activation policy for the application. Defaults to - // applicationActivationPolicyRegular. - ActivationPolicy ActivationPolicy - // If set to true, the application will terminate when the last window is closed. - ApplicationShouldTerminateAfterLastWindowClosed bool -} diff --git a/v3/pkg/application/options_application_win.go b/v3/pkg/application/options_application_win.go deleted file mode 100644 index b5a7afdb7ec..00000000000 --- a/v3/pkg/application/options_application_win.go +++ /dev/null @@ -1,21 +0,0 @@ -package application - -// WindowsOptions contains options for Windows applications. -type WindowsOptions struct { - - // WndProcInterceptor is a function that will be called for every message sent in the application. - // Use this to hook into the main message loop. This is useful for handling custom window messages. - // If `shouldReturn` is `true` then `returnCode` will be returned by the main message loop. - // If `shouldReturn` is `false` then returnCode will be ignored and the message will be processed by the main message loop. - WndProcInterceptor func(hwnd uintptr, msg uint32, wParam, lParam uintptr) (returnCode uintptr, shouldReturn bool) - - // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. - DisableQuitOnLastWindowClosed bool - - // Path where the WebView2 stores the user data. If empty %APPDATA%\[BinaryName.exe] will be used. - // If the path is not valid, a messagebox will be displayed with the error and the app will exit with error code. - WebviewUserDataPath string - - // Path to the directory with WebView2 executables. If empty WebView2 installed in the system will be used. - WebviewBrowserPath string -} diff --git a/v3/pkg/application/options_lin.go b/v3/pkg/application/options_lin.go deleted file mode 100644 index 3a471902ce3..00000000000 --- a/v3/pkg/application/options_lin.go +++ /dev/null @@ -1,43 +0,0 @@ -package application - -// WebviewGpuPolicy values used for determining the webview's hardware acceleration policy. -type WebviewGpuPolicy int - -const ( - // WebviewGpuPolicyAlways Hardware acceleration is always enabled. - WebviewGpuPolicyAlways WebviewGpuPolicy = iota - // WebviewGpuPolicyOnDemand Hardware acceleration is enabled/disabled as request by web contents. - WebviewGpuPolicyOnDemand - // WebviewGpuPolicyNever Hardware acceleration is always disabled. - WebviewGpuPolicyNever -) - -// LinuxWindow specific to Linux windows -type LinuxWindow struct { - // Icon Sets up the icon representing the window. This icon is used when the window is minimized - // (also known as iconified). - Icon []byte - - // WindowIsTranslucent sets the window's background to transparent when enabled. - WindowIsTranslucent bool - - // WebviewGpuPolicy used for determining the hardware acceleration policy for the webview. - // - WebviewGpuPolicyAlways - // - WebviewGpuPolicyOnDemand - // - WebviewGpuPolicyNever - // - // Due to https://github.com/wailsapp/wails/issues/2977, if options.Linux is nil - // in the call to wails.Run(), WebviewGpuPolicy is set by default to WebviewGpuPolicyNever. - // Client code may override this behavior by passing a non-nil Options and set - // WebviewGpuPolicy as needed. - WebviewGpuPolicy WebviewGpuPolicy - - // ProgramName is used to set the program's name for the window manager via GTK's g_set_prgname(). - //This name should not be localized. [see the docs] - // - //When a .desktop file is created this value helps with window grouping and desktop icons when the .desktop file's Name - //property differs form the executable's filename. - // - //[see the docs]: https://docs.gtk.org/glib/func.set_prgname.html - ProgramName string -} diff --git a/v3/pkg/application/options_mac.go b/v3/pkg/application/options_mac.go deleted file mode 100644 index 6255cc5cec1..00000000000 --- a/v3/pkg/application/options_mac.go +++ /dev/null @@ -1,165 +0,0 @@ -package application - -import ( - "github.com/leaanthony/u" - "github.com/wailsapp/wails/v3/pkg/events" -) - -// MacBackdrop is the backdrop type for macOS -type MacBackdrop int - -const ( - // MacBackdropNormal - The default value. The window will have a normal opaque background. - MacBackdropNormal MacBackdrop = iota - // MacBackdropTransparent - The window will have a transparent background, with the content underneath it being visible - MacBackdropTransparent - // MacBackdropTranslucent - The window will have a translucent background, with the content underneath it being "fuzzy" or "frosted" - MacBackdropTranslucent -) - -// MacToolbarStyle is the style of toolbar for macOS -type MacToolbarStyle int - -const ( - // MacToolbarStyleAutomatic - The default value. The style will be determined by the window's given configuration - MacToolbarStyleAutomatic MacToolbarStyle = iota - // MacToolbarStyleExpanded - The toolbar will appear below the window title - MacToolbarStyleExpanded - // MacToolbarStylePreference - The toolbar will appear below the window title and the items in the toolbar will attempt to have equal widths when possible - MacToolbarStylePreference - // MacToolbarStyleUnified - The window title will appear inline with the toolbar when visible - MacToolbarStyleUnified - // MacToolbarStyleUnifiedCompact - Same as MacToolbarStyleUnified, but with reduced margins in the toolbar allowing more focus to be on the contents of the window - MacToolbarStyleUnifiedCompact -) - -// MacWindow contains macOS specific options for Webview Windows -type MacWindow struct { - // Backdrop is the backdrop type for the window - Backdrop MacBackdrop - // DisableShadow will disable the window shadow - DisableShadow bool - // TitleBar contains options for the Mac titlebar - TitleBar MacTitleBar - // Appearance is the appearance type for the window - Appearance MacAppearanceType - // InvisibleTitleBarHeight defines the height of an invisible titlebar which responds to dragging - InvisibleTitleBarHeight int - // Maps events from platform specific to common event types - EventMapping map[events.WindowEventType]events.WindowEventType - - // EnableFraudulentWebsiteWarnings will enable warnings for fraudulent websites. - // Default: false - EnableFraudulentWebsiteWarnings bool - - // WebviewPreferences contains preferences for the webview - WebviewPreferences MacWebviewPreferences - - // Disables the minimise button - DisableMinimiseButton bool - - // Disables the maximise button - DisableMaximiseButton bool - - // Disables the close button - DisableCloseButton bool -} - -// MacWebviewPreferences contains preferences for the Mac webview -type MacWebviewPreferences struct { - // TabFocusesLinks will enable tabbing to links - TabFocusesLinks u.Bool - // TextInteractionEnabled will enable text interaction - TextInteractionEnabled u.Bool - // FullscreenEnabled will enable fullscreen - FullscreenEnabled u.Bool -} - -// MacTitleBar contains options for the Mac titlebar -type MacTitleBar struct { - // AppearsTransparent will make the titlebar transparent - AppearsTransparent bool - // Hide will hide the titlebar - Hide bool - // HideTitle will hide the title - HideTitle bool - // FullSizeContent will extend the window content to the full size of the window - FullSizeContent bool - // UseToolbar will use a toolbar instead of a titlebar - UseToolbar bool - // HideToolbarSeparator will hide the toolbar separator - HideToolbarSeparator bool - // ShowToolbarWhenFullscreen will keep the toolbar visible when the window is in fullscreen mode - ShowToolbarWhenFullscreen bool - // ToolbarStyle is the style of toolbar to use - ToolbarStyle MacToolbarStyle -} - -// MacTitleBarDefault results in the default Mac MacTitleBar -var MacTitleBarDefault = MacTitleBar{ - AppearsTransparent: false, - Hide: false, - HideTitle: false, - FullSizeContent: false, - UseToolbar: false, - HideToolbarSeparator: false, -} - -// Credit: Comments from Electron site - -// MacTitleBarHidden results in a hidden title bar and a full size content window, -// yet the title bar still has the standard window controls (“traffic lights”) -// in the top left. -var MacTitleBarHidden = MacTitleBar{ - AppearsTransparent: true, - Hide: false, - HideTitle: true, - FullSizeContent: true, - UseToolbar: false, - HideToolbarSeparator: false, -} - -// MacTitleBarHiddenInset results in a hidden title bar with an alternative look where -// the traffic light buttons are slightly more inset from the window edge. -var MacTitleBarHiddenInset = MacTitleBar{ - AppearsTransparent: true, - Hide: false, - HideTitle: true, - FullSizeContent: true, - UseToolbar: true, - HideToolbarSeparator: true, -} - -// MacTitleBarHiddenInsetUnified results in a hidden title bar with an alternative look where -// the traffic light buttons are even more inset from the window edge. -var MacTitleBarHiddenInsetUnified = MacTitleBar{ - AppearsTransparent: true, - Hide: false, - HideTitle: true, - FullSizeContent: true, - UseToolbar: true, - HideToolbarSeparator: true, - ToolbarStyle: MacToolbarStyleUnified, -} - -// MacAppearanceType is a type of Appearance for Cocoa windows -type MacAppearanceType string - -const ( - // DefaultAppearance uses the default system value - DefaultAppearance MacAppearanceType = "" - // NSAppearanceNameAqua - The standard light system appearance. - NSAppearanceNameAqua MacAppearanceType = "NSAppearanceNameAqua" - // NSAppearanceNameDarkAqua - The standard dark system appearance. - NSAppearanceNameDarkAqua MacAppearanceType = "NSAppearanceNameDarkAqua" - // NSAppearanceNameVibrantLight - The light vibrant appearance - NSAppearanceNameVibrantLight MacAppearanceType = "NSAppearanceNameVibrantLight" - // NSAppearanceNameAccessibilityHighContrastAqua - A high-contrast version of the standard light system appearance. - NSAppearanceNameAccessibilityHighContrastAqua MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastAqua" - // NSAppearanceNameAccessibilityHighContrastDarkAqua - A high-contrast version of the standard dark system appearance. - NSAppearanceNameAccessibilityHighContrastDarkAqua MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastDarkAqua" - // NSAppearanceNameAccessibilityHighContrastVibrantLight - A high-contrast version of the light vibrant appearance. - NSAppearanceNameAccessibilityHighContrastVibrantLight MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastVibrantLight" - // NSAppearanceNameAccessibilityHighContrastVibrantDark - A high-contrast version of the dark vibrant appearance. - NSAppearanceNameAccessibilityHighContrastVibrantDark MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastVibrantDark" -) diff --git a/v3/pkg/application/options_webview_window.go b/v3/pkg/application/options_webview_window.go deleted file mode 100644 index c20585076ff..00000000000 --- a/v3/pkg/application/options_webview_window.go +++ /dev/null @@ -1,164 +0,0 @@ -package application - -type WindowState int - -const ( - WindowStateNormal WindowState = iota - WindowStateMinimised - WindowStateMaximised - WindowStateFullscreen -) - -type WebviewWindowOptions struct { - // Name is a unique identifier that can be given to a window. - Name string - - // Title is the title of the window. - Title string - - // Width is the starting width of the window. - Width int - - // Height is the starting height of the window. - Height int - - // AlwaysOnTop will make the window float above other windows. - AlwaysOnTop bool - - // URL is the URL to load in the window. - URL string - - // DisableResize will disable the ability to resize the window. - DisableResize bool - - // Frameless will remove the window frame. - Frameless bool - - // MinWidth is the minimum width of the window. - MinWidth int - - // MinHeight is the minimum height of the window. - MinHeight int - - // MaxWidth is the maximum width of the window. - MaxWidth int - - // MaxHeight is the maximum height of the window. - MaxHeight int - - // StartState indicates the state of the window when it is first shown. - // Default: WindowStateNormal - StartState WindowState - - // Centered will center the window on the screen. - Centered bool - - // BackgroundType is the type of background to use for the window. - // Default: BackgroundTypeSolid - BackgroundType BackgroundType - - // BackgroundColour is the colour to use for the window background. - BackgroundColour RGBA - - // HTML is the HTML to load in the window. - HTML string - - // JS is the JavaScript to load in the window. - JS string - - // CSS is the CSS to load in the window. - CSS string - - // X is the starting X position of the window. - X int - - // Y is the starting Y position of the window. - Y int - - // TransparentTitlebar will make the titlebar transparent. - // TODO: Move to mac window options - FullscreenButtonEnabled bool - - // Hidden will hide the window when it is first created. - Hidden bool - - // Zoom is the zoom level of the window. - Zoom float64 - - // ZoomControlEnabled will enable the zoom control. - ZoomControlEnabled bool - - // EnableDragAndDrop will enable drag and drop. - EnableDragAndDrop bool - - // OpenInspectorOnStartup will open the inspector when the window is first shown. - OpenInspectorOnStartup bool - - // Mac options - Mac MacWindow - - // Windows options - Windows WindowsWindow - - // Linux options - Linux LinuxWindow - - // ShouldClose is called when the window is about to close. - // Return true to allow the window to close, or false to prevent it from closing. - ShouldClose func(window *WebviewWindow) bool - - // If true, the window's devtools will be available (default true in builds without the `production` build tag) - DevToolsEnabled bool - - // If true, the window's default context menu will be disabled (default false) - DefaultContextMenuDisabled bool - - // KeyBindings is a map of key bindings to functions - KeyBindings map[string]func(window *WebviewWindow) - - // IgnoreMouseEvents will ignore mouse events in the window (Windows + Mac only) - IgnoreMouseEvents bool -} - -var WebviewWindowDefaults = &WebviewWindowOptions{ - Title: "", - Width: 800, - Height: 600, - URL: "", - BackgroundColour: RGBA{ - Red: 255, - Green: 255, - Blue: 255, - Alpha: 255, - }, -} - -type RGBA struct { - Red, Green, Blue, Alpha uint8 -} - -func NewRGBA(red, green, blue, alpha uint8) RGBA { - return RGBA{ - Red: red, - Green: green, - Blue: blue, - Alpha: alpha, - } -} - -func NewRGB(red, green, blue uint8) RGBA { - return RGBA{ - Red: red, - Green: green, - Blue: blue, - Alpha: 255, - } -} - -type BackgroundType int - -const ( - BackgroundTypeSolid BackgroundType = iota - BackgroundTypeTransparent - BackgroundTypeTranslucent -) diff --git a/v3/pkg/application/options_webview_window_win.go b/v3/pkg/application/options_webview_window_win.go deleted file mode 100644 index 9c51219a481..00000000000 --- a/v3/pkg/application/options_webview_window_win.go +++ /dev/null @@ -1,154 +0,0 @@ -package application - -import ( - "github.com/wailsapp/wails/v3/pkg/events" -) - -type BackdropType int32 -type DragEffect int32 - -const ( - // DragEffectNone is used to indicate that the drop target cannot accept the data. - DragEffectNone DragEffect = 1 - // DragEffectCopy is used to indicate that the data is copied to the drop target. - DragEffectCopy DragEffect = 2 - // DragEffectMove is used to indicate that the data is removed from the drag source. - DragEffectMove DragEffect = 3 - // DragEffectLink is used to indicate that a link to the original data is established. - DragEffectLink DragEffect = 4 - // DragEffectScroll is used to indicate that the target can be scrolled while dragging to locate a drop position that is not currently visible in the target. - -) - -const ( - Auto BackdropType = 0 - None BackdropType = 1 - Mica BackdropType = 2 - Acrylic BackdropType = 3 - Tabbed BackdropType = 4 -) - -type CoreWebView2PermissionKind uint32 - -const ( - CoreWebView2PermissionKindUnknownPermission CoreWebView2PermissionKind = iota - CoreWebView2PermissionKindMicrophone - CoreWebView2PermissionKindCamera - CoreWebView2PermissionKindGeolocation - CoreWebView2PermissionKindNotifications - CoreWebView2PermissionKindOtherSensors - CoreWebView2PermissionKindClipboardRead -) - -type CoreWebView2PermissionState uint32 - -const ( - CoreWebView2PermissionStateDefault CoreWebView2PermissionState = iota - CoreWebView2PermissionStateAllow - CoreWebView2PermissionStateDeny -) - -type WindowsWindow struct { - // Select the type of translucent backdrop. Requires Windows 11 22621 or later. - // Only used when window's `BackgroundType` is set to `BackgroundTypeTranslucent`. - // Default: Auto - BackdropType BackdropType - - // Disable the icon in the titlebar - // Default: false - DisableIcon bool - - // Theme (Dark / Light / SystemDefault) - // Default: SystemDefault - The application will follow system theme changes. - Theme Theme - - // Specify custom colours to use for dark/light mode - // Default: nil - CustomTheme *ThemeSettings - - // Disable all window decorations in Frameless mode, which means no "Aero Shadow" and no "Rounded Corner" will be shown. - // "Rounded Corners" are only available on Windows 11. - // Default: false - DisableFramelessWindowDecorations bool - - // WindowMask is used to set the window shape. Use a PNG with an alpha channel to create a custom shape. - // Default: nil - WindowMask []byte - - // WindowMaskDraggable is used to make the window draggable by clicking on the window mask. - // Default: false - WindowMaskDraggable bool - - // WebviewGpuIsDisabled is used to enable / disable GPU acceleration for the webview - // Default: false - WebviewGpuIsDisabled bool - - // ResizeDebounceMS is the amount of time to debounce redraws of webview2 - // when resizing the window - // Default: 0 - ResizeDebounceMS uint16 - - // Disable the menu bar for this window - // Default: false - DisableMenu bool - - // Event mapping for the window. This allows you to define a translation from one event to another. - // Default: nil - EventMapping map[events.WindowEventType]events.WindowEventType - - // HiddenOnTaskbar hides the window from the taskbar - // Default: false - HiddenOnTaskbar bool - - // EnableSwipeGestures enables swipe gestures for the window - // Default: false - EnableSwipeGestures bool - - // EnableFraudulentWebsiteWarnings will enable warnings for fraudulent websites. - // Default: false - EnableFraudulentWebsiteWarnings bool - - // Menu is the menu to use for the window. - Menu *Menu - - // Drag Cursor Effects - OnEnterEffect DragEffect - OnOverEffect DragEffect - - // Permissions map for WebView2. If empty, default permissions will be granted. - Permissions map[CoreWebView2PermissionKind]CoreWebView2PermissionState - - // Disables the minimise button - DisableMinimiseButton bool - - // Disables the maximise button - DisableMaximiseButton bool -} - -type Theme int - -const ( - // SystemDefault will use whatever the system theme is. The application will follow system theme changes. - SystemDefault Theme = 0 - // Dark Mode - Dark Theme = 1 - // Light Mode - Light Theme = 2 -) - -// ThemeSettings defines custom colours to use in dark or light mode. -// They may be set using the hex values: 0x00BBGGRR -type ThemeSettings struct { - DarkModeTitleBar int32 - DarkModeTitleBarInactive int32 - DarkModeTitleText int32 - DarkModeTitleTextInactive int32 - DarkModeBorder int32 - DarkModeBorderInactive int32 - LightModeTitleBar int32 - LightModeTitleBarInactive int32 - LightModeTitleText int32 - LightModeTitleTextInactive int32 - LightModeBorder int32 - LightModeBorderInactive int32 -} diff --git a/v3/pkg/application/webview_window_options.go b/v3/pkg/application/webview_window_options.go new file mode 100644 index 00000000000..d84bce87443 --- /dev/null +++ b/v3/pkg/application/webview_window_options.go @@ -0,0 +1,525 @@ +package application + +import ( + "github.com/leaanthony/u" + "github.com/wailsapp/wails/v3/pkg/events" +) + +type WindowState int + +const ( + WindowStateNormal WindowState = iota + WindowStateMinimised + WindowStateMaximised + WindowStateFullscreen +) + +type WebviewWindowOptions struct { + // Name is a unique identifier that can be given to a window. + Name string + + // Title is the title of the window. + Title string + + // Width is the starting width of the window. + Width int + + // Height is the starting height of the window. + Height int + + // AlwaysOnTop will make the window float above other windows. + AlwaysOnTop bool + + // URL is the URL to load in the window. + URL string + + // DisableResize will disable the ability to resize the window. + DisableResize bool + + // Frameless will remove the window frame. + Frameless bool + + // MinWidth is the minimum width of the window. + MinWidth int + + // MinHeight is the minimum height of the window. + MinHeight int + + // MaxWidth is the maximum width of the window. + MaxWidth int + + // MaxHeight is the maximum height of the window. + MaxHeight int + + // StartState indicates the state of the window when it is first shown. + // Default: WindowStateNormal + StartState WindowState + + // Centered will center the window on the screen. + Centered bool + + // BackgroundType is the type of background to use for the window. + // Default: BackgroundTypeSolid + BackgroundType BackgroundType + + // BackgroundColour is the colour to use for the window background. + BackgroundColour RGBA + + // HTML is the HTML to load in the window. + HTML string + + // JS is the JavaScript to load in the window. + JS string + + // CSS is the CSS to load in the window. + CSS string + + // X is the starting X position of the window. + X int + + // Y is the starting Y position of the window. + Y int + + // TransparentTitlebar will make the titlebar transparent. + // TODO: Move to mac window options + FullscreenButtonEnabled bool + + // Hidden will hide the window when it is first created. + Hidden bool + + // Zoom is the zoom level of the window. + Zoom float64 + + // ZoomControlEnabled will enable the zoom control. + ZoomControlEnabled bool + + // EnableDragAndDrop will enable drag and drop. + EnableDragAndDrop bool + + // OpenInspectorOnStartup will open the inspector when the window is first shown. + OpenInspectorOnStartup bool + + // Mac options + Mac MacWindow + + // Windows options + Windows WindowsWindow + + // Linux options + Linux LinuxWindow + + // ShouldClose is called when the window is about to close. + // Return true to allow the window to close, or false to prevent it from closing. + ShouldClose func(window *WebviewWindow) bool + + // If true, the window's devtools will be available (default true in builds without the `production` build tag) + DevToolsEnabled bool + + // If true, the window's default context menu will be disabled (default false) + DefaultContextMenuDisabled bool + + // KeyBindings is a map of key bindings to functions + KeyBindings map[string]func(window *WebviewWindow) + + // IgnoreMouseEvents will ignore mouse events in the window (Windows + Mac only) + IgnoreMouseEvents bool +} + +var WebviewWindowDefaults = &WebviewWindowOptions{ + Title: "", + Width: 800, + Height: 600, + URL: "", + BackgroundColour: RGBA{ + Red: 255, + Green: 255, + Blue: 255, + Alpha: 255, + }, +} + +type RGBA struct { + Red, Green, Blue, Alpha uint8 +} + +func NewRGBA(red, green, blue, alpha uint8) RGBA { + return RGBA{ + Red: red, + Green: green, + Blue: blue, + Alpha: alpha, + } +} + +func NewRGB(red, green, blue uint8) RGBA { + return RGBA{ + Red: red, + Green: green, + Blue: blue, + Alpha: 255, + } +} + +type BackgroundType int + +const ( + BackgroundTypeSolid BackgroundType = iota + BackgroundTypeTransparent + BackgroundTypeTranslucent +) + +/******* Windows Options *******/ + +type BackdropType int32 +type DragEffect int32 + +const ( + // DragEffectNone is used to indicate that the drop target cannot accept the data. + DragEffectNone DragEffect = 1 + // DragEffectCopy is used to indicate that the data is copied to the drop target. + DragEffectCopy DragEffect = 2 + // DragEffectMove is used to indicate that the data is removed from the drag source. + DragEffectMove DragEffect = 3 + // DragEffectLink is used to indicate that a link to the original data is established. + DragEffectLink DragEffect = 4 + // DragEffectScroll is used to indicate that the target can be scrolled while dragging to locate a drop position that is not currently visible in the target. + +) + +const ( + Auto BackdropType = 0 + None BackdropType = 1 + Mica BackdropType = 2 + Acrylic BackdropType = 3 + Tabbed BackdropType = 4 +) + +type CoreWebView2PermissionKind uint32 + +const ( + CoreWebView2PermissionKindUnknownPermission CoreWebView2PermissionKind = iota + CoreWebView2PermissionKindMicrophone + CoreWebView2PermissionKindCamera + CoreWebView2PermissionKindGeolocation + CoreWebView2PermissionKindNotifications + CoreWebView2PermissionKindOtherSensors + CoreWebView2PermissionKindClipboardRead +) + +type CoreWebView2PermissionState uint32 + +const ( + CoreWebView2PermissionStateDefault CoreWebView2PermissionState = iota + CoreWebView2PermissionStateAllow + CoreWebView2PermissionStateDeny +) + +type WindowsWindow struct { + // Select the type of translucent backdrop. Requires Windows 11 22621 or later. + // Only used when window's `BackgroundType` is set to `BackgroundTypeTranslucent`. + // Default: Auto + BackdropType BackdropType + + // Disable the icon in the titlebar + // Default: false + DisableIcon bool + + // Theme (Dark / Light / SystemDefault) + // Default: SystemDefault - The application will follow system theme changes. + Theme Theme + + // Specify custom colours to use for dark/light mode + // Default: nil + CustomTheme *ThemeSettings + + // Disable all window decorations in Frameless mode, which means no "Aero Shadow" and no "Rounded Corner" will be shown. + // "Rounded Corners" are only available on Windows 11. + // Default: false + DisableFramelessWindowDecorations bool + + // WindowMask is used to set the window shape. Use a PNG with an alpha channel to create a custom shape. + // Default: nil + WindowMask []byte + + // WindowMaskDraggable is used to make the window draggable by clicking on the window mask. + // Default: false + WindowMaskDraggable bool + + // WebviewGpuIsDisabled is used to enable / disable GPU acceleration for the webview + // Default: false + WebviewGpuIsDisabled bool + + // ResizeDebounceMS is the amount of time to debounce redraws of webview2 + // when resizing the window + // Default: 0 + ResizeDebounceMS uint16 + + // Disable the menu bar for this window + // Default: false + DisableMenu bool + + // Event mapping for the window. This allows you to define a translation from one event to another. + // Default: nil + EventMapping map[events.WindowEventType]events.WindowEventType + + // HiddenOnTaskbar hides the window from the taskbar + // Default: false + HiddenOnTaskbar bool + + // EnableSwipeGestures enables swipe gestures for the window + // Default: false + EnableSwipeGestures bool + + // EnableFraudulentWebsiteWarnings will enable warnings for fraudulent websites. + // Default: false + EnableFraudulentWebsiteWarnings bool + + // Menu is the menu to use for the window. + Menu *Menu + + // Drag Cursor Effects + OnEnterEffect DragEffect + OnOverEffect DragEffect + + // Permissions map for WebView2. If empty, default permissions will be granted. + Permissions map[CoreWebView2PermissionKind]CoreWebView2PermissionState + + // Disables the minimise button + DisableMinimiseButton bool + + // Disables the maximise button + DisableMaximiseButton bool +} + +type Theme int + +const ( + // SystemDefault will use whatever the system theme is. The application will follow system theme changes. + SystemDefault Theme = 0 + // Dark Mode + Dark Theme = 1 + // Light Mode + Light Theme = 2 +) + +// ThemeSettings defines custom colours to use in dark or light mode. +// They may be set using the hex values: 0x00BBGGRR +type ThemeSettings struct { + DarkModeTitleBar int32 + DarkModeTitleBarInactive int32 + DarkModeTitleText int32 + DarkModeTitleTextInactive int32 + DarkModeBorder int32 + DarkModeBorderInactive int32 + LightModeTitleBar int32 + LightModeTitleBarInactive int32 + LightModeTitleText int32 + LightModeTitleTextInactive int32 + LightModeBorder int32 + LightModeBorderInactive int32 +} + +/****** Mac Options *******/ + +// MacBackdrop is the backdrop type for macOS +type MacBackdrop int + +const ( + // MacBackdropNormal - The default value. The window will have a normal opaque background. + MacBackdropNormal MacBackdrop = iota + // MacBackdropTransparent - The window will have a transparent background, with the content underneath it being visible + MacBackdropTransparent + // MacBackdropTranslucent - The window will have a translucent background, with the content underneath it being "fuzzy" or "frosted" + MacBackdropTranslucent +) + +// MacToolbarStyle is the style of toolbar for macOS +type MacToolbarStyle int + +const ( + // MacToolbarStyleAutomatic - The default value. The style will be determined by the window's given configuration + MacToolbarStyleAutomatic MacToolbarStyle = iota + // MacToolbarStyleExpanded - The toolbar will appear below the window title + MacToolbarStyleExpanded + // MacToolbarStylePreference - The toolbar will appear below the window title and the items in the toolbar will attempt to have equal widths when possible + MacToolbarStylePreference + // MacToolbarStyleUnified - The window title will appear inline with the toolbar when visible + MacToolbarStyleUnified + // MacToolbarStyleUnifiedCompact - Same as MacToolbarStyleUnified, but with reduced margins in the toolbar allowing more focus to be on the contents of the window + MacToolbarStyleUnifiedCompact +) + +// MacWindow contains macOS specific options for Webview Windows +type MacWindow struct { + // Backdrop is the backdrop type for the window + Backdrop MacBackdrop + // DisableShadow will disable the window shadow + DisableShadow bool + // TitleBar contains options for the Mac titlebar + TitleBar MacTitleBar + // Appearance is the appearance type for the window + Appearance MacAppearanceType + // InvisibleTitleBarHeight defines the height of an invisible titlebar which responds to dragging + InvisibleTitleBarHeight int + // Maps events from platform specific to common event types + EventMapping map[events.WindowEventType]events.WindowEventType + + // EnableFraudulentWebsiteWarnings will enable warnings for fraudulent websites. + // Default: false + EnableFraudulentWebsiteWarnings bool + + // WebviewPreferences contains preferences for the webview + WebviewPreferences MacWebviewPreferences + + // Disables the minimise button + DisableMinimiseButton bool + + // Disables the maximise button + DisableMaximiseButton bool + + // Disables the close button + DisableCloseButton bool +} + +// MacWebviewPreferences contains preferences for the Mac webview +type MacWebviewPreferences struct { + // TabFocusesLinks will enable tabbing to links + TabFocusesLinks u.Bool + // TextInteractionEnabled will enable text interaction + TextInteractionEnabled u.Bool + // FullscreenEnabled will enable fullscreen + FullscreenEnabled u.Bool +} + +// MacTitleBar contains options for the Mac titlebar +type MacTitleBar struct { + // AppearsTransparent will make the titlebar transparent + AppearsTransparent bool + // Hide will hide the titlebar + Hide bool + // HideTitle will hide the title + HideTitle bool + // FullSizeContent will extend the window content to the full size of the window + FullSizeContent bool + // UseToolbar will use a toolbar instead of a titlebar + UseToolbar bool + // HideToolbarSeparator will hide the toolbar separator + HideToolbarSeparator bool + // ShowToolbarWhenFullscreen will keep the toolbar visible when the window is in fullscreen mode + ShowToolbarWhenFullscreen bool + // ToolbarStyle is the style of toolbar to use + ToolbarStyle MacToolbarStyle +} + +// MacTitleBarDefault results in the default Mac MacTitleBar +var MacTitleBarDefault = MacTitleBar{ + AppearsTransparent: false, + Hide: false, + HideTitle: false, + FullSizeContent: false, + UseToolbar: false, + HideToolbarSeparator: false, +} + +// Credit: Comments from Electron site + +// MacTitleBarHidden results in a hidden title bar and a full size content window, +// yet the title bar still has the standard window controls (“traffic lights”) +// in the top left. +var MacTitleBarHidden = MacTitleBar{ + AppearsTransparent: true, + Hide: false, + HideTitle: true, + FullSizeContent: true, + UseToolbar: false, + HideToolbarSeparator: false, +} + +// MacTitleBarHiddenInset results in a hidden title bar with an alternative look where +// the traffic light buttons are slightly more inset from the window edge. +var MacTitleBarHiddenInset = MacTitleBar{ + AppearsTransparent: true, + Hide: false, + HideTitle: true, + FullSizeContent: true, + UseToolbar: true, + HideToolbarSeparator: true, +} + +// MacTitleBarHiddenInsetUnified results in a hidden title bar with an alternative look where +// the traffic light buttons are even more inset from the window edge. +var MacTitleBarHiddenInsetUnified = MacTitleBar{ + AppearsTransparent: true, + Hide: false, + HideTitle: true, + FullSizeContent: true, + UseToolbar: true, + HideToolbarSeparator: true, + ToolbarStyle: MacToolbarStyleUnified, +} + +// MacAppearanceType is a type of Appearance for Cocoa windows +type MacAppearanceType string + +const ( + // DefaultAppearance uses the default system value + DefaultAppearance MacAppearanceType = "" + // NSAppearanceNameAqua - The standard light system appearance. + NSAppearanceNameAqua MacAppearanceType = "NSAppearanceNameAqua" + // NSAppearanceNameDarkAqua - The standard dark system appearance. + NSAppearanceNameDarkAqua MacAppearanceType = "NSAppearanceNameDarkAqua" + // NSAppearanceNameVibrantLight - The light vibrant appearance + NSAppearanceNameVibrantLight MacAppearanceType = "NSAppearanceNameVibrantLight" + // NSAppearanceNameAccessibilityHighContrastAqua - A high-contrast version of the standard light system appearance. + NSAppearanceNameAccessibilityHighContrastAqua MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastAqua" + // NSAppearanceNameAccessibilityHighContrastDarkAqua - A high-contrast version of the standard dark system appearance. + NSAppearanceNameAccessibilityHighContrastDarkAqua MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastDarkAqua" + // NSAppearanceNameAccessibilityHighContrastVibrantLight - A high-contrast version of the light vibrant appearance. + NSAppearanceNameAccessibilityHighContrastVibrantLight MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastVibrantLight" + // NSAppearanceNameAccessibilityHighContrastVibrantDark - A high-contrast version of the dark vibrant appearance. + NSAppearanceNameAccessibilityHighContrastVibrantDark MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastVibrantDark" +) + +/******** Linux Options ********/ + +// WebviewGpuPolicy values used for determining the webview's hardware acceleration policy. +type WebviewGpuPolicy int + +const ( + // WebviewGpuPolicyAlways Hardware acceleration is always enabled. + WebviewGpuPolicyAlways WebviewGpuPolicy = iota + // WebviewGpuPolicyOnDemand Hardware acceleration is enabled/disabled as request by web contents. + WebviewGpuPolicyOnDemand + // WebviewGpuPolicyNever Hardware acceleration is always disabled. + WebviewGpuPolicyNever +) + +// LinuxWindow specific to Linux windows +type LinuxWindow struct { + // Icon Sets up the icon representing the window. This icon is used when the window is minimized + // (also known as iconified). + Icon []byte + + // WindowIsTranslucent sets the window's background to transparent when enabled. + WindowIsTranslucent bool + + // WebviewGpuPolicy used for determining the hardware acceleration policy for the webview. + // - WebviewGpuPolicyAlways + // - WebviewGpuPolicyOnDemand + // - WebviewGpuPolicyNever + // + // Due to https://github.com/wailsapp/wails/issues/2977, if options.Linux is nil + // in the call to wails.Run(), WebviewGpuPolicy is set by default to WebviewGpuPolicyNever. + // Client code may override this behavior by passing a non-nil Options and set + // WebviewGpuPolicy as needed. + WebviewGpuPolicy WebviewGpuPolicy + + // ProgramName is used to set the program's name for the window manager via GTK's g_set_prgname(). + //This name should not be localized. [see the docs] + // + //When a .desktop file is created this value helps with window grouping and desktop icons when the .desktop file's Name + //property differs form the executable's filename. + // + //[see the docs]: https://docs.gtk.org/glib/func.set_prgname.html + ProgramName string +} From ec2ce3fcfbfb7e0a41c565698a1bb1204ff0eecb Mon Sep 17 00:00:00 2001 From: atterpac <89053530+atterpac@users.noreply.github.com> Date: Sat, 16 Mar 2024 17:17:17 -0700 Subject: [PATCH 092/369] Fix appimage file sourcing (#3306) Add findGTKFiles to source webkit files for appimage generation s --- v3/internal/commands/appimage.go | 61 ++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/v3/internal/commands/appimage.go b/v3/internal/commands/appimage.go index 6888c5aaa05..f3238da0132 100644 --- a/v3/internal/commands/appimage.go +++ b/v3/internal/commands/appimage.go @@ -2,12 +2,15 @@ package commands import ( _ "embed" + "errors" "fmt" - "github.com/pterm/pterm" - "github.com/wailsapp/wails/v3/internal/s" "os" "path/filepath" + "strings" "sync" + + "github.com/pterm/pterm" + "github.com/wailsapp/wails/v3/internal/s" ) //go:embed linuxdeploy-plugin-gtk.sh @@ -110,9 +113,10 @@ func generateAppImage(options *GenerateAppImageOptions) error { wg.Wait() log(p, "Processing GTK files.") - files := s.FINDFILES("/usr/lib", "WebKitNetworkProcess", "WebKitWebProcess", "libwebkit2gtkinjectedbundle.so") - if len(files) != 3 { - return fmt.Errorf("unable to locate all WebKit libraries") + filesNeeded := []string{"WebKitWebProcess", "WebKitNetworkProcess", "libwebkit2gtkinjectedbundle.so"} + files, err := findGTKFiles(filesNeeded) + if err != nil { + return err } s.CD(appDir) for _, file := range files { @@ -130,7 +134,7 @@ func generateAppImage(options *GenerateAppImageOptions) error { s.COPY(file, targetDir) } // Copy GTK Plugin - err := os.WriteFile(filepath.Join(options.BuildDir, "linuxdeploy-plugin-gtk.sh"), gtkPlugin, 0755) + err = os.WriteFile(filepath.Join(options.BuildDir, "linuxdeploy-plugin-gtk.sh"), gtkPlugin, 0755) if err != nil { return err } @@ -173,3 +177,48 @@ func generateAppImage(options *GenerateAppImageOptions) error { log(p, "AppImage created: "+targetFile) return nil } + +func findGTKFiles(files []string) ([]string, error) { + notFound := []string{} + found := []string{} + err := filepath.Walk("/usr/", func(path string, info os.FileInfo, err error) error { + if err != nil { + if os.IsPermission(err) { + return nil + } + return err + } + + if info.IsDir() { + return nil + } + + for _, fileName := range files { + if strings.HasSuffix(path, fileName) { + found = append(found, path) + break + } + } + + return nil + }) + if err != nil { + return nil, err + } + for _, fileName := range files { + fileFound := false + for _, foundPath := range found { + if strings.HasSuffix(foundPath, fileName) { + fileFound = true + break + } + } + if !fileFound { + notFound = append(notFound, fileName) + } + } + if len(notFound) > 0 { + return nil, errors.New("Unable to locate all required files: " + strings.Join(notFound, ", ")) + } + return found, nil +} From 839e42edde6d688524c239376643dc37c2f70e64 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 Mar 2024 11:37:14 +1100 Subject: [PATCH 093/369] Bump the npm_and_yarn group across 2 directories with 2 updates (#3319) Bumps the npm_and_yarn group with 1 update in the /v2/internal/frontend/runtime directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite). Bumps the npm_and_yarn group with 1 update in the /website directory: [follow-redirects](https://github.com/follow-redirects/follow-redirects). Updates `vite` from 3.1.8 to 3.2.8 - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v3.2.8/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v3.2.8/packages/vite) Updates `follow-redirects` from 1.15.4 to 1.15.6 - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.4...v1.15.6) --- updated-dependencies: - dependency-name: vite dependency-type: indirect dependency-group: npm_and_yarn-security-group - dependency-name: follow-redirects dependency-type: indirect dependency-group: npm_and_yarn-security-group ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../frontend/runtime/package-lock.json | 52 +- website/pnpm-lock.yaml | 578 +++++++++++++----- 2 files changed, 467 insertions(+), 163 deletions(-) diff --git a/v2/internal/frontend/runtime/package-lock.json b/v2/internal/frontend/runtime/package-lock.json index daf6ecf28b6..cea8c249178 100644 --- a/v2/internal/frontend/runtime/package-lock.json +++ b/v2/internal/frontend/runtime/package-lock.json @@ -784,9 +784,9 @@ } }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -1514,9 +1514,9 @@ } }, "node_modules/rollup": { - "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -1865,15 +1865,15 @@ } }, "node_modules/vite": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.8.tgz", - "integrity": "sha512-m7jJe3nufUbuOfotkntGFupinL/fmuTNuQmiVE7cH2IZMuf4UbfbGYMUT3jVWgGYuRVLY9j8NnrRqgw5rr5QTg==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.8.tgz", + "integrity": "sha512-EtQU16PLIJpAZol2cTLttNP1mX6L0SyI0pgQB1VOoWeQnMSvtiwovV3D6NcjN8CZQWWyESD2v5NGnpz5RvgOZA==", "dev": true, "dependencies": { "esbuild": "^0.15.9", - "postcss": "^8.4.16", + "postcss": "^8.4.18", "resolve": "^1.22.1", - "rollup": "~2.78.0" + "rollup": "^2.79.1" }, "bin": { "vite": "bin/vite.js" @@ -1885,12 +1885,17 @@ "fsevents": "~2.3.2" }, "peerDependencies": { + "@types/node": ">= 14", "less": "*", "sass": "*", "stylus": "*", + "sugarss": "*", "terser": "^5.4.0" }, "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, "less": { "optional": true }, @@ -1900,6 +1905,9 @@ "stylus": { "optional": true }, + "sugarss": { + "optional": true + }, "terser": { "optional": true } @@ -2528,9 +2536,9 @@ } }, "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "optional": true }, @@ -3046,9 +3054,9 @@ } }, "rollup": { - "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -3330,16 +3338,16 @@ } }, "vite": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.8.tgz", - "integrity": "sha512-m7jJe3nufUbuOfotkntGFupinL/fmuTNuQmiVE7cH2IZMuf4UbfbGYMUT3jVWgGYuRVLY9j8NnrRqgw5rr5QTg==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.8.tgz", + "integrity": "sha512-EtQU16PLIJpAZol2cTLttNP1mX6L0SyI0pgQB1VOoWeQnMSvtiwovV3D6NcjN8CZQWWyESD2v5NGnpz5RvgOZA==", "dev": true, "requires": { "esbuild": "^0.15.9", "fsevents": "~2.3.2", - "postcss": "^8.4.16", + "postcss": "^8.4.18", "resolve": "^1.22.1", - "rollup": "~2.78.0" + "rollup": "^2.79.1" } }, "vitest": { diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index 51792e1c4d9..9d2917fae4c 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -10,13 +10,13 @@ dependencies: version: 1.19.2 '@docusaurus/core': specifier: ^2.4.0 - version: 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + version: 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/preset-classic': specifier: ^2.4.0 - version: 2.4.0(@algolia/client-search@4.17.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + version: 2.4.0(@algolia/client-search@4.22.1)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/theme-search-algolia': specifier: ^2.4.0 - version: 2.4.0(@algolia/client-search@4.17.0)(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + version: 2.4.0(@algolia/client-search@4.22.1)(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@mdx-js/react': specifier: ^1.6.22 version: 1.6.22(react@17.0.2) @@ -28,7 +28,7 @@ dependencies: version: 1.2.1 file-loader: specifier: ^6.2.0 - version: 6.2.0(webpack@5.79.0) + version: 6.2.0(webpack@5.90.3) prism-react-renderer: specifier: ^1.3.5 version: 1.3.5(react@17.0.2) @@ -43,7 +43,7 @@ dependencies: version: 3.2.23 swc-loader: specifier: ^0.2.3 - version: 0.2.3(@swc/core@1.3.7)(webpack@5.79.0) + version: 0.2.3(@swc/core@1.3.7)(webpack@5.90.3) devDependencies: '@crowdin/cli': @@ -61,14 +61,14 @@ packages: '@algolia/autocomplete-shared': 1.7.4 dev: false - /@algolia/autocomplete-preset-algolia@1.7.4(@algolia/client-search@4.17.0)(algoliasearch@4.17.0): + /@algolia/autocomplete-preset-algolia@1.7.4(@algolia/client-search@4.22.1)(algoliasearch@4.17.0): resolution: {integrity: sha512-s37hrvLEIfcmKY8VU9LsAXgm2yfmkdHT3DnA3SgHaY93yjZ2qL57wzb5QweVkYuEBZkT2PIREvRoLXC2sxTbpQ==} peerDependencies: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' dependencies: '@algolia/autocomplete-shared': 1.7.4 - '@algolia/client-search': 4.17.0 + '@algolia/client-search': 4.22.1 algoliasearch: 4.17.0 dev: false @@ -86,6 +86,10 @@ packages: resolution: {integrity: sha512-g8mXzkrcUBIPZaulAuqE7xyHhLAYAcF2xSch7d9dABheybaU3U91LjBX6eJTEB7XVhEsgK4Smi27vWtAJRhIKQ==} dev: false + /@algolia/cache-common@4.22.1: + resolution: {integrity: sha512-TJMBKqZNKYB9TptRRjSUtevJeQVXRmg6rk9qgFKWvOy8jhCPdyNZV1nB3SKGufzvTVbomAukFR8guu/8NRKBTA==} + dev: false + /@algolia/cache-in-memory@4.17.0: resolution: {integrity: sha512-PT32ciC/xI8z919d0oknWVu3kMfTlhQn3MKxDln3pkn+yA7F7xrxSALysxquv+MhFfNAcrtQ/oVvQVBAQSHtdw==} dependencies: @@ -116,6 +120,13 @@ packages: '@algolia/transporter': 4.17.0 dev: false + /@algolia/client-common@4.22.1: + resolution: {integrity: sha512-IvaL5v9mZtm4k4QHbBGDmU3wa/mKokmqNBqPj0K7lcR8ZDKzUorhcGp/u8PkPC/e0zoHSTvRh7TRkGX3Lm7iOQ==} + dependencies: + '@algolia/requester-common': 4.22.1 + '@algolia/transporter': 4.22.1 + dev: false + /@algolia/client-personalization@4.17.0: resolution: {integrity: sha512-RMzN4dZLIta1YuwT7QC9o+OeGz2cU6eTOlGNE/6RcUBLOU3l9tkCOdln5dPE2jp8GZXPl2yk54b2nSs1+pAjqw==} dependencies: @@ -132,6 +143,14 @@ packages: '@algolia/transporter': 4.17.0 dev: false + /@algolia/client-search@4.22.1: + resolution: {integrity: sha512-yb05NA4tNaOgx3+rOxAmFztgMTtGBi97X7PC3jyNeGiwkAjOZc2QrdZBYyIdcDLoI09N0gjtpClcackoTN0gPA==} + dependencies: + '@algolia/client-common': 4.22.1 + '@algolia/requester-common': 4.22.1 + '@algolia/transporter': 4.22.1 + dev: false + /@algolia/events@4.0.1: resolution: {integrity: sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==} dev: false @@ -140,6 +159,10 @@ packages: resolution: {integrity: sha512-DGuoZqpTmIKJFDeyAJ7M8E/LOenIjWiOsg1XJ1OqAU/eofp49JfqXxbfgctlVZVmDABIyOz8LqEoJ6ZP4DTyvw==} dev: false + /@algolia/logger-common@4.22.1: + resolution: {integrity: sha512-OnTFymd2odHSO39r4DSWRFETkBufnY2iGUZNrMXpIhF5cmFE8pGoINNPzwg02QLBlGSaLqdKy0bM8S0GyqPLBg==} + dev: false + /@algolia/logger-console@4.17.0: resolution: {integrity: sha512-zMPvugQV/gbXUvWBCzihw6m7oxIKp48w37QBIUu/XqQQfxhjoOE9xyfJr1KldUt5FrYOKZJVsJaEjTsu+bIgQg==} dependencies: @@ -156,6 +179,10 @@ packages: resolution: {integrity: sha512-XJjmWFEUlHu0ijvcHBoixuXfEoiRUdyzQM6YwTuB8usJNIgShua8ouFlRWF8iCeag0vZZiUm4S2WCVBPkdxFgg==} dev: false + /@algolia/requester-common@4.22.1: + resolution: {integrity: sha512-dgvhSAtg2MJnR+BxrIFqlLtkLlVVhas9HgYKMk2Uxiy5m6/8HZBL40JVAMb2LovoPFs9I/EWIoFVjOrFwzn5Qg==} + dev: false + /@algolia/requester-node-http@4.17.0: resolution: {integrity: sha512-bpb/wDA1aC6WxxM8v7TsFspB7yBN3nqCGs2H1OADolQR/hiAIjAxusbuMxVbRFOdaUvAIqioIIkWvZdpYNIn8w==} dependencies: @@ -170,6 +197,14 @@ packages: '@algolia/requester-common': 4.17.0 dev: false + /@algolia/transporter@4.22.1: + resolution: {integrity: sha512-kzWgc2c9IdxMa3YqA6TN0NW5VrKYYW/BELIn7vnLyn+U/RFdZ4lxxt9/8yq3DKV5snvoDzzO4ClyejZRdV3lMQ==} + dependencies: + '@algolia/cache-common': 4.22.1 + '@algolia/logger-common': 4.22.1 + '@algolia/requester-common': 4.22.1 + dev: false + /@ampproject/remapping@2.2.1: resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} engines: {node: '>=6.0.0'} @@ -1672,7 +1707,7 @@ packages: resolution: {integrity: sha512-6SCwI7P8ao+se1TUsdZ7B4XzL+gqeQZnBc+2EONZlcVa0dVrk0NjETxozFKgMv0eEGH8QzP1fkN+A1rH61l4eg==} dev: false - /@docsearch/react@3.3.3(@algolia/client-search@4.17.0)(react-dom@17.0.2)(react@17.0.2): + /@docsearch/react@3.3.3(@algolia/client-search@4.22.1)(react-dom@17.0.2)(react@17.0.2): resolution: {integrity: sha512-pLa0cxnl+G0FuIDuYlW+EBK6Rw2jwLw9B1RHIeS4N4s2VhsfJ/wzeCi3CWcs5yVfxLd5ZK50t//TMA5e79YT7Q==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' @@ -1687,7 +1722,7 @@ packages: optional: true dependencies: '@algolia/autocomplete-core': 1.7.4 - '@algolia/autocomplete-preset-algolia': 1.7.4(@algolia/client-search@4.17.0)(algoliasearch@4.17.0) + '@algolia/autocomplete-preset-algolia': 1.7.4(@algolia/client-search@4.22.1)(algoliasearch@4.17.0) '@docsearch/css': 3.3.3 algoliasearch: 4.17.0 react: 17.0.2 @@ -1696,7 +1731,7 @@ packages: - '@algolia/client-search' dev: false - /@docusaurus/core@2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/core@2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-J55/WEoIpRcLf3afO5POHPguVZosKmJEQWKBL+K7TAnfuE7i+Y0NPLlkKtnWCehagGsgTqClfQEexH/UT4kELA==} engines: {node: '>=16.14'} hasBin: true @@ -1752,10 +1787,10 @@ packages: lodash: 4.17.21 mini-css-extract-plugin: 2.7.5(webpack@5.78.0) postcss: 8.4.31 - postcss-loader: 7.2.4(@types/node@18.15.11)(postcss@8.4.31)(ts-node@10.9.1)(typescript@5.0.4)(webpack@5.78.0) + postcss-loader: 7.2.4(@types/node@20.11.28)(postcss@8.4.31)(ts-node@10.9.2)(typescript@5.4.2)(webpack@5.78.0) prompts: 2.4.2 react: 17.0.2 - react-dev-utils: 12.0.1(typescript@5.0.4)(webpack@5.78.0) + react-dev-utils: 12.0.1(typescript@5.4.2)(webpack@5.78.0) react-dom: 17.0.2(react@17.0.2) react-helmet-async: 1.3.0(react-dom@17.0.2)(react@17.0.2) react-loadable: /@docusaurus/react-loadable@5.5.2(react@17.0.2) @@ -1860,7 +1895,7 @@ packages: '@docusaurus/react-loadable': 5.5.2(react@17.0.2) '@docusaurus/types': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@types/history': 4.7.11 - '@types/react': 18.0.35 + '@types/react': 18.2.66 '@types/react-router-config': 5.0.7 '@types/react-router-dom': 5.3.3 react: 17.0.2 @@ -1874,14 +1909,14 @@ packages: - webpack-cli dev: false - /@docusaurus/plugin-content-blog@2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/plugin-content-blog@2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-YwkAkVUxtxoBAIj/MCb4ohN0SCtHBs4AS75jMhPpf67qf3j+U/4n33cELq7567hwyZ6fMz2GPJcVmctzlGGThQ==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/logger': 2.4.0 '@docusaurus/mdx-loader': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/types': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) @@ -1919,14 +1954,14 @@ packages: - webpack-cli dev: false - /@docusaurus/plugin-content-docs@2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/plugin-content-docs@2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-ic/Z/ZN5Rk/RQo+Io6rUGpToOtNbtPloMR2JcGwC1xT2riMu6zzfSwmBi9tHJgdXH6CB5jG+0dOZZO8QS5tmDg==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/logger': 2.4.0 '@docusaurus/mdx-loader': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/module-type-aliases': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) @@ -1964,14 +1999,14 @@ packages: - webpack-cli dev: false - /@docusaurus/plugin-content-pages@2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/plugin-content-pages@2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-Pk2pOeOxk8MeU3mrTU0XLIgP9NZixbdcJmJ7RUFrZp1Aj42nd0RhIT14BGvXXyqb8yTQlk4DmYGAzqOfBsFyGw==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/mdx-loader': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/types': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/utils': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7) @@ -2001,14 +2036,14 @@ packages: - webpack-cli dev: false - /@docusaurus/plugin-debug@2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/plugin-debug@2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-KC56DdYjYT7Txyux71vXHXGYZuP6yYtqwClvYpjKreWIHWus5Zt6VNi23rMZv3/QKhOCrN64zplUbdfQMvddBQ==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/types': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/utils': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7) fs-extra: 10.1.0 @@ -2038,14 +2073,14 @@ packages: - webpack-cli dev: false - /@docusaurus/plugin-google-analytics@2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/plugin-google-analytics@2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-uGUzX67DOAIglygdNrmMOvEp8qG03X20jMWadeqVQktS6nADvozpSLGx4J0xbkblhJkUzN21WiilsP9iVP+zkw==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/types': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/utils-validation': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7) react: 17.0.2 @@ -2071,14 +2106,14 @@ packages: - webpack-cli dev: false - /@docusaurus/plugin-google-gtag@2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/plugin-google-gtag@2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-adj/70DANaQs2+TF/nRdMezDXFAV/O/pjAbUgmKBlyOTq5qoMe0Tk4muvQIwWUmiUQxFJe+sKlZGM771ownyOg==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/types': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/utils-validation': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7) react: 17.0.2 @@ -2104,14 +2139,14 @@ packages: - webpack-cli dev: false - /@docusaurus/plugin-google-tag-manager@2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/plugin-google-tag-manager@2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-E66uGcYs4l7yitmp/8kMEVQftFPwV9iC62ORh47Veqzs6ExwnhzBkJmwDnwIysHBF1vlxnzET0Fl2LfL5fRR3A==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/types': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/utils-validation': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7) react: 17.0.2 @@ -2137,14 +2172,14 @@ packages: - webpack-cli dev: false - /@docusaurus/plugin-sitemap@2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/plugin-sitemap@2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-pZxh+ygfnI657sN8a/FkYVIAmVv0CGk71QMKqJBOfMmDHNN1FeDeFkBjWP49ejBqpqAhjufkv5UWq3UOu2soCw==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/logger': 2.4.0 '@docusaurus/types': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/utils': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7) @@ -2175,25 +2210,25 @@ packages: - webpack-cli dev: false - /@docusaurus/preset-classic@2.4.0(@algolia/client-search@4.17.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/preset-classic@2.4.0(@algolia/client-search@4.22.1)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-/5z5o/9bc6+P5ool2y01PbJhoGddEGsC0ej1MF6mCoazk8A+kW4feoUd68l7Bnv01rCnG3xy7kHUQP97Y0grUA==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/plugin-content-blog': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/plugin-content-docs': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/plugin-content-pages': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/plugin-debug': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/plugin-google-analytics': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/plugin-google-gtag': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/plugin-google-tag-manager': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/plugin-sitemap': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/theme-classic': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/theme-common': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/theme-search-algolia': 2.4.0(@algolia/client-search@4.17.0)(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/plugin-content-blog': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/plugin-content-docs': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/plugin-content-pages': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/plugin-debug': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/plugin-google-analytics': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/plugin-google-gtag': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/plugin-google-tag-manager': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/plugin-sitemap': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/theme-classic': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/theme-common': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/theme-search-algolia': 2.4.0(@algolia/client-search@4.22.1)(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/types': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) react: 17.0.2 react-dom: 17.0.2(react@17.0.2) @@ -2225,25 +2260,25 @@ packages: peerDependencies: react: '*' dependencies: - '@types/react': 18.0.35 + '@types/react': 18.2.66 prop-types: 15.8.1 react: 17.0.2 dev: false - /@docusaurus/theme-classic@2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/theme-classic@2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-GMDX5WU6Z0OC65eQFgl3iNNEbI9IMJz9f6KnOyuMxNUR6q0qVLsKCNopFUDfFNJ55UU50o7P7o21yVhkwpfJ9w==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/mdx-loader': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/module-type-aliases': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) - '@docusaurus/plugin-content-blog': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/plugin-content-docs': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/plugin-content-pages': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/theme-common': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/plugin-content-blog': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/plugin-content-docs': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/plugin-content-pages': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/theme-common': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/theme-translations': 2.4.0 '@docusaurus/types': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/utils': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7) @@ -2284,7 +2319,7 @@ packages: - webpack-cli dev: false - /@docusaurus/theme-common@2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/theme-common@2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-IkG/l5f/FLY6cBIxtPmFnxpuPzc5TupuqlOx+XDN+035MdQcAh8wHXXZJAkTeYDeZ3anIUSUIvWa7/nRKoQEfg==} engines: {node: '>=16.14'} peerDependencies: @@ -2293,9 +2328,9 @@ packages: dependencies: '@docusaurus/mdx-loader': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) '@docusaurus/module-type-aliases': 2.4.0(@swc/core@1.3.7)(react-dom@17.0.2)(react@17.0.2) - '@docusaurus/plugin-content-blog': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/plugin-content-docs': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/plugin-content-pages': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/plugin-content-blog': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/plugin-content-docs': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/plugin-content-pages': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/utils': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7) '@docusaurus/utils-common': 2.4.0(@docusaurus/types@2.4.0) '@types/history': 4.7.11 @@ -2330,18 +2365,18 @@ packages: - webpack-cli dev: false - /@docusaurus/theme-search-algolia@2.4.0(@algolia/client-search@4.17.0)(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4): + /@docusaurus/theme-search-algolia@2.4.0(@algolia/client-search@4.22.1)(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-pPCJSCL1Qt4pu/Z0uxBAuke0yEBbxh0s4fOvimna7TEcBLPq0x06/K78AaABXrTVQM6S0vdocFl9EoNgU17hqA==} engines: {node: '>=16.14'} peerDependencies: react: ^16.8.4 || ^17.0.0 react-dom: ^16.8.4 || ^17.0.0 dependencies: - '@docsearch/react': 3.3.3(@algolia/client-search@4.17.0)(react-dom@17.0.2)(react@17.0.2) - '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docsearch/react': 3.3.3(@algolia/client-search@4.22.1)(react-dom@17.0.2)(react@17.0.2) + '@docusaurus/core': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/logger': 2.4.0 - '@docusaurus/plugin-content-docs': 2.4.0(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) - '@docusaurus/theme-common': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@18.15.11)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.1)(typescript@5.0.4) + '@docusaurus/plugin-content-docs': 2.4.0(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) + '@docusaurus/theme-common': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7)(@types/node@20.11.28)(react-dom@17.0.2)(react@17.0.2)(ts-node@10.9.2)(typescript@5.4.2) '@docusaurus/theme-translations': 2.4.0 '@docusaurus/utils': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7) '@docusaurus/utils-validation': 2.4.0(@docusaurus/types@2.4.0)(@swc/core@1.3.7) @@ -2512,13 +2547,22 @@ packages: '@jridgewell/trace-mapping': 0.3.18 dev: false + /@jridgewell/gen-mapping@0.3.5: + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + dev: false + /@jridgewell/resolve-uri@3.1.0: resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} engines: {node: '>=6.0.0'} dev: false - /@jridgewell/resolve-uri@3.1.1: - resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + /@jridgewell/resolve-uri@3.1.2: + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} dev: false @@ -2527,6 +2571,11 @@ packages: engines: {node: '>=6.0.0'} dev: false + /@jridgewell/set-array@1.2.1: + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + dev: false + /@jridgewell/source-map@0.3.3: resolution: {integrity: sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==} dependencies: @@ -2534,6 +2583,13 @@ packages: '@jridgewell/trace-mapping': 0.3.18 dev: false + /@jridgewell/source-map@0.3.6: + resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + dev: false + /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} dev: false @@ -2549,10 +2605,17 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: false + /@jridgewell/trace-mapping@0.3.25: + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false + /@jridgewell/trace-mapping@0.3.9: resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} dependencies: - '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 dev: false @@ -2994,8 +3057,8 @@ packages: resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} dev: false - /@tsconfig/node16@1.0.3: - resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} dev: false /@types/body-parser@1.19.2: @@ -3031,6 +3094,13 @@ packages: '@types/estree': 0.0.51 dev: false + /@types/eslint-scope@3.7.7: + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} + dependencies: + '@types/eslint': 8.56.5 + '@types/estree': 1.0.5 + dev: false + /@types/eslint@8.37.0: resolution: {integrity: sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==} dependencies: @@ -3038,12 +3108,19 @@ packages: '@types/json-schema': 7.0.11 dev: false + /@types/eslint@8.56.5: + resolution: {integrity: sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==} + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.15 + dev: false + /@types/estree@0.0.51: resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==} dev: false - /@types/estree@1.0.0: - resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} dev: false /@types/express-serve-static-core@4.17.33: @@ -3103,6 +3180,10 @@ packages: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} dev: false + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: false + /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: @@ -3127,6 +3208,12 @@ packages: resolution: {integrity: sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==} dev: false + /@types/node@20.11.28: + resolution: {integrity: sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==} + dependencies: + undici-types: 5.26.5 + dev: false + /@types/parse-json@4.0.0: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} dev: false @@ -3135,8 +3222,8 @@ packages: resolution: {integrity: sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==} dev: false - /@types/prop-types@15.7.5: - resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} + /@types/prop-types@15.7.11: + resolution: {integrity: sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==} dev: false /@types/qs@6.9.7: @@ -3151,7 +3238,7 @@ packages: resolution: {integrity: sha512-pFFVXUIydHlcJP6wJm7sDii5mD/bCmmAY0wQzq+M+uX7bqS95AQqHZWP1iNMKrWVQSuHIzj5qi9BvrtLX2/T4w==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.0.35 + '@types/react': 18.2.66 '@types/react-router': 5.1.20 dev: false @@ -3159,7 +3246,7 @@ packages: resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.0.35 + '@types/react': 18.2.66 '@types/react-router': 5.1.20 dev: false @@ -3167,15 +3254,23 @@ packages: resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==} dependencies: '@types/history': 4.7.11 - '@types/react': 18.0.35 + '@types/react': 18.2.66 dev: false /@types/react@18.0.35: resolution: {integrity: sha512-6Laome31HpetaIUGFWl1VQ3mdSImwxtFZ39rh059a1MNnKGqBpC88J6NJ8n/Is3Qx7CefDGLgf/KhN/sYCf7ag==} dependencies: - '@types/prop-types': 15.7.5 - '@types/scheduler': 0.16.3 - csstype: 3.1.2 + '@types/prop-types': 15.7.11 + '@types/scheduler': 0.16.8 + csstype: 3.1.3 + dev: false + + /@types/react@18.2.66: + resolution: {integrity: sha512-OYTmMI4UigXeFMF/j4uv0lBBEbongSgptPrHBxqME44h9+yNov+oL6Z3ocJKo0WyXR84sQUNeyIp9MRfckvZpg==} + dependencies: + '@types/prop-types': 15.7.11 + '@types/scheduler': 0.16.8 + csstype: 3.1.3 dev: false /@types/responselike@1.0.0: @@ -3194,8 +3289,8 @@ packages: '@types/node': 18.15.11 dev: false - /@types/scheduler@0.16.3: - resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} + /@types/scheduler@0.16.8: + resolution: {integrity: sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==} dev: false /@types/serve-index@1.9.1: @@ -3244,18 +3339,37 @@ packages: '@webassemblyjs/helper-wasm-bytecode': 1.11.1 dev: false + /@webassemblyjs/ast@1.12.1: + resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} + dependencies: + '@webassemblyjs/helper-numbers': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + dev: false + /@webassemblyjs/floating-point-hex-parser@1.11.1: resolution: {integrity: sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==} dev: false + /@webassemblyjs/floating-point-hex-parser@1.11.6: + resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} + dev: false + /@webassemblyjs/helper-api-error@1.11.1: resolution: {integrity: sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==} dev: false + /@webassemblyjs/helper-api-error@1.11.6: + resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} + dev: false + /@webassemblyjs/helper-buffer@1.11.1: resolution: {integrity: sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==} dev: false + /@webassemblyjs/helper-buffer@1.12.1: + resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==} + dev: false + /@webassemblyjs/helper-numbers@1.11.1: resolution: {integrity: sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==} dependencies: @@ -3264,10 +3378,22 @@ packages: '@xtuc/long': 4.2.2 dev: false + /@webassemblyjs/helper-numbers@1.11.6: + resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@xtuc/long': 4.2.2 + dev: false + /@webassemblyjs/helper-wasm-bytecode@1.11.1: resolution: {integrity: sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==} dev: false + /@webassemblyjs/helper-wasm-bytecode@1.11.6: + resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} + dev: false + /@webassemblyjs/helper-wasm-section@1.11.1: resolution: {integrity: sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==} dependencies: @@ -3277,22 +3403,47 @@ packages: '@webassemblyjs/wasm-gen': 1.11.1 dev: false + /@webassemblyjs/helper-wasm-section@1.12.1: + resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/wasm-gen': 1.12.1 + dev: false + /@webassemblyjs/ieee754@1.11.1: resolution: {integrity: sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==} dependencies: '@xtuc/ieee754': 1.2.0 dev: false + /@webassemblyjs/ieee754@1.11.6: + resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} + dependencies: + '@xtuc/ieee754': 1.2.0 + dev: false + /@webassemblyjs/leb128@1.11.1: resolution: {integrity: sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==} dependencies: '@xtuc/long': 4.2.2 dev: false + /@webassemblyjs/leb128@1.11.6: + resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} + dependencies: + '@xtuc/long': 4.2.2 + dev: false + /@webassemblyjs/utf8@1.11.1: resolution: {integrity: sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==} dev: false + /@webassemblyjs/utf8@1.11.6: + resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} + dev: false + /@webassemblyjs/wasm-edit@1.11.1: resolution: {integrity: sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==} dependencies: @@ -3306,6 +3457,19 @@ packages: '@webassemblyjs/wast-printer': 1.11.1 dev: false + /@webassemblyjs/wasm-edit@1.12.1: + resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-wasm-section': 1.12.1 + '@webassemblyjs/wasm-gen': 1.12.1 + '@webassemblyjs/wasm-opt': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + '@webassemblyjs/wast-printer': 1.12.1 + dev: false + /@webassemblyjs/wasm-gen@1.11.1: resolution: {integrity: sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==} dependencies: @@ -3316,6 +3480,16 @@ packages: '@webassemblyjs/utf8': 1.11.1 dev: false + /@webassemblyjs/wasm-gen@1.12.1: + resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: false + /@webassemblyjs/wasm-opt@1.11.1: resolution: {integrity: sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==} dependencies: @@ -3325,6 +3499,15 @@ packages: '@webassemblyjs/wasm-parser': 1.11.1 dev: false + /@webassemblyjs/wasm-opt@1.12.1: + resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-buffer': 1.12.1 + '@webassemblyjs/wasm-gen': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + dev: false + /@webassemblyjs/wasm-parser@1.11.1: resolution: {integrity: sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==} dependencies: @@ -3336,6 +3519,17 @@ packages: '@webassemblyjs/utf8': 1.11.1 dev: false + /@webassemblyjs/wasm-parser@1.12.1: + resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/helper-api-error': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: false + /@webassemblyjs/wast-printer@1.11.1: resolution: {integrity: sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==} dependencies: @@ -3343,6 +3537,13 @@ packages: '@xtuc/long': 4.2.2 dev: false + /@webassemblyjs/wast-printer@1.12.1: + resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} + dependencies: + '@webassemblyjs/ast': 1.12.1 + '@xtuc/long': 4.2.2 + dev: false + /@xtuc/ieee754@1.2.0: resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} dev: false @@ -3367,11 +3568,30 @@ packages: acorn: 8.8.2 dev: false + /acorn-import-assertions@1.9.0(acorn@8.11.3): + resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + peerDependencies: + acorn: ^8 + dependencies: + acorn: 8.11.3 + dev: false + /acorn-walk@8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} dev: false + /acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + dev: false + + /acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: false + /acorn@8.8.2: resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} engines: {node: '>=0.4.0'} @@ -3573,7 +3793,7 @@ packages: /axios@0.21.3: resolution: {integrity: sha512-JtoZ3Ndke/+Iwt5n+BgSli/3idTvpt5OjKyoCmz4LX5+lPiY5l7C1colYezhlxThjNa/NhngCUWZSZFypIFuaA==} dependencies: - follow-redirects: 1.15.4 + follow-redirects: 1.15.6 transitivePeerDependencies: - debug dev: false @@ -3581,7 +3801,7 @@ packages: /axios@0.25.0: resolution: {integrity: sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==} dependencies: - follow-redirects: 1.15.4 + follow-redirects: 1.15.6 transitivePeerDependencies: - debug dev: false @@ -3768,6 +3988,17 @@ packages: update-browserslist-db: 1.0.10(browserslist@4.21.5) dev: false + /browserslist@4.23.0: + resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001597 + electron-to-chromium: 1.4.708 + node-releases: 2.0.14 + update-browserslist-db: 1.0.13(browserslist@4.23.0) + dev: false + /buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} dev: true @@ -3841,6 +4072,10 @@ packages: resolution: {integrity: sha512-lZim4iUHhGcy5p+Ri/G7m84hJwncj+Kz7S5aD4hoQfslKZJgt0tHc/hafVbqHC5bbhHb+mrW2JOUHkI5KH7toQ==} dev: false + /caniuse-lite@1.0.30001597: + resolution: {integrity: sha512-7LjJvmQU6Sj7bL0j5b5WY/3n7utXUJvAe1lxhsHDbLmwX9mdL86Yjtr+5SRCyf8qME4M7pU2hswj0FpyBVCv9w==} + dev: false + /ccount@1.1.0: resolution: {integrity: sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==} dev: false @@ -3910,7 +4145,7 @@ packages: normalize-path: 3.0.0 readdirp: 3.6.0 optionalDependencies: - fsevents: 2.3.2 + fsevents: 2.3.3 dev: false /chownr@1.1.4: @@ -4172,7 +4407,7 @@ packages: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} dev: false - /cosmiconfig-typescript-loader@4.3.0(@types/node@18.15.11)(cosmiconfig@8.1.3)(ts-node@10.9.1)(typescript@5.0.4): + /cosmiconfig-typescript-loader@4.3.0(@types/node@20.11.28)(cosmiconfig@8.1.3)(ts-node@10.9.2)(typescript@5.4.2): resolution: {integrity: sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==} engines: {node: '>=12', npm: '>=6'} peerDependencies: @@ -4181,10 +4416,10 @@ packages: ts-node: '>=10' typescript: '>=3' dependencies: - '@types/node': 18.15.11 + '@types/node': 20.11.28 cosmiconfig: 8.1.3 - ts-node: 10.9.1(@swc/core@1.3.7)(@types/node@18.15.11)(typescript@5.0.4) - typescript: 5.0.4 + ts-node: 10.9.2(@swc/core@1.3.7)(@types/node@20.11.28)(typescript@5.4.2) + typescript: 5.4.2 dev: false /cosmiconfig@6.0.0: @@ -4426,8 +4661,8 @@ packages: css-tree: 1.1.3 dev: false - /csstype@3.1.2: - resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + /csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} dev: false /debug@2.6.9: @@ -4667,6 +4902,10 @@ packages: resolution: {integrity: sha512-UTkCbNTAcGXABmEnQrGcW4m3cG6fcyBfD4KDF0iyEAlbrGZiY9dmslyDAGOD1Kr5biN2F743Y30aRCOtau35Vw==} dev: false + /electron-to-chromium@1.4.708: + resolution: {integrity: sha512-iWgEEvREL4GTXXHKohhh33+6Y8XkPI5eHihDmm8zUk5Zo7HICEW+wI/j5kJ2tbuNUCXJ/sNXa03ajW635DiJXA==} + dev: false + /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: false @@ -4703,6 +4942,14 @@ packages: tapable: 2.2.1 dev: false + /enhanced-resolve@5.16.0: + resolution: {integrity: sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: false + /entities@2.2.0: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} dev: false @@ -4722,8 +4969,8 @@ packages: resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} dev: false - /es-module-lexer@1.2.1: - resolution: {integrity: sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==} + /es-module-lexer@1.4.1: + resolution: {integrity: sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==} dev: false /escalade@3.1.1: @@ -4731,6 +4978,11 @@ packages: engines: {node: '>=6'} dev: false + /escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + dev: false + /escape-goat@2.1.1: resolution: {integrity: sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==} engines: {node: '>=8'} @@ -4966,7 +5218,7 @@ packages: webpack: 5.78.0(@swc/core@1.3.7) dev: false - /file-loader@6.2.0(webpack@5.79.0): + /file-loader@6.2.0(webpack@5.90.3): resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -4974,7 +5226,7 @@ packages: dependencies: loader-utils: 2.0.4 schema-utils: 3.1.1 - webpack: 5.79.0(@swc/core@1.3.7) + webpack: 5.90.3(@swc/core@1.3.7) dev: false /filesize@8.0.7: @@ -5048,8 +5300,8 @@ packages: - encoding dev: false - /follow-redirects@1.15.4: - resolution: {integrity: sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==} + /follow-redirects@1.15.6: + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -5058,7 +5310,7 @@ packages: optional: true dev: false - /fork-ts-checker-webpack-plugin@6.5.3(typescript@5.0.4)(webpack@5.78.0): + /fork-ts-checker-webpack-plugin@6.5.3(typescript@5.4.2)(webpack@5.78.0): resolution: {integrity: sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==} engines: {node: '>=10', yarn: '>=1.0.0'} peerDependencies: @@ -5085,7 +5337,7 @@ packages: schema-utils: 2.7.0 semver: 7.4.0 tapable: 1.1.3 - typescript: 5.0.4 + typescript: 5.4.2 webpack: 5.78.0(@swc/core@1.3.7) dev: false @@ -5135,8 +5387,8 @@ packages: /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - /fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true @@ -5550,7 +5802,7 @@ packages: engines: {node: '>=8.0.0'} dependencies: eventemitter3: 4.0.7 - follow-redirects: 1.15.4 + follow-redirects: 1.15.6 requires-port: 1.0.0 transitivePeerDependencies: - debug @@ -6349,6 +6601,10 @@ packages: resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} dev: false + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + dev: false + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -6742,7 +6998,7 @@ packages: postcss-selector-parser: 6.0.11 dev: false - /postcss-loader@7.2.4(@types/node@18.15.11)(postcss@8.4.31)(ts-node@10.9.1)(typescript@5.0.4)(webpack@5.78.0): + /postcss-loader@7.2.4(@types/node@20.11.28)(postcss@8.4.31)(ts-node@10.9.2)(typescript@5.4.2)(webpack@5.78.0): resolution: {integrity: sha512-F88rpxxNspo5hatIc+orYwZDtHFaVFOSIVAx+fBfJC1GmhWbVmPWtmg2gXKE1OxJbneOSGn8PWdIwsZFcruS+w==} engines: {node: '>= 14.15.0'} peerDependencies: @@ -6757,12 +7013,12 @@ packages: optional: true dependencies: cosmiconfig: 8.1.3 - cosmiconfig-typescript-loader: 4.3.0(@types/node@18.15.11)(cosmiconfig@8.1.3)(ts-node@10.9.1)(typescript@5.0.4) + cosmiconfig-typescript-loader: 4.3.0(@types/node@20.11.28)(cosmiconfig@8.1.3)(ts-node@10.9.2)(typescript@5.4.2) klona: 2.0.6 postcss: 8.4.31 semver: 7.4.0 - ts-node: 10.9.1(@swc/core@1.3.7)(@types/node@18.15.11)(typescript@5.0.4) - typescript: 5.0.4 + ts-node: 10.9.2(@swc/core@1.3.7)(@types/node@20.11.28)(typescript@5.4.2) + typescript: 5.4.2 webpack: 5.78.0(@swc/core@1.3.7) transitivePeerDependencies: - '@types/node' @@ -7247,7 +7503,7 @@ packages: pure-color: 1.3.0 dev: false - /react-dev-utils@12.0.1(typescript@5.0.4)(webpack@5.78.0): + /react-dev-utils@12.0.1(typescript@5.4.2)(webpack@5.78.0): resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} engines: {node: '>=14'} peerDependencies: @@ -7266,7 +7522,7 @@ packages: escape-string-regexp: 4.0.0 filesize: 8.0.7 find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 6.5.3(typescript@5.0.4)(webpack@5.78.0) + fork-ts-checker-webpack-plugin: 6.5.3(typescript@5.4.2)(webpack@5.78.0) global-modules: 2.0.0 globby: 11.1.0 gzip-size: 6.0.0 @@ -7281,7 +7537,7 @@ packages: shell-quote: 1.8.1 strip-ansi: 6.0.1 text-table: 0.2.0 - typescript: 5.0.4 + typescript: 5.4.2 webpack: 5.78.0(@swc/core@1.3.7) transitivePeerDependencies: - eslint @@ -7741,11 +7997,11 @@ packages: ajv-keywords: 3.5.2(ajv@6.12.6) dev: false - /schema-utils@3.1.2: - resolution: {integrity: sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==} + /schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/json-schema': 7.0.11 + '@types/json-schema': 7.0.15 ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) dev: false @@ -7831,6 +8087,12 @@ packages: randombytes: 2.1.0 dev: false + /serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + dependencies: + randombytes: 2.1.0 + dev: false + /serve-handler@6.1.5: resolution: {integrity: sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==} dependencies: @@ -8190,14 +8452,14 @@ packages: stable: 0.1.8 dev: false - /swc-loader@0.2.3(@swc/core@1.3.7)(webpack@5.79.0): + /swc-loader@0.2.3(@swc/core@1.3.7)(webpack@5.90.3): resolution: {integrity: sha512-D1p6XXURfSPleZZA/Lipb3A8pZ17fP4NObZvFCDjK/OKljroqDpPmsBdTraWhVBqUNpcWBQY1imWdoPScRlQ7A==} peerDependencies: '@swc/core': ^1.2.147 webpack: '>=2' dependencies: '@swc/core': 1.3.7 - webpack: 5.79.0(@swc/core@1.3.7) + webpack: 5.90.3(@swc/core@1.3.7) dev: false /tapable@1.1.3: @@ -8223,8 +8485,8 @@ packages: yallist: 3.1.1 dev: true - /terser-webpack-plugin@5.3.7(@swc/core@1.3.7)(webpack@5.78.0): - resolution: {integrity: sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==} + /terser-webpack-plugin@5.3.10(@swc/core@1.3.7)(webpack@5.90.3): + resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} engines: {node: '>= 10.13.0'} peerDependencies: '@swc/core': '*' @@ -8239,16 +8501,16 @@ packages: uglify-js: optional: true dependencies: - '@jridgewell/trace-mapping': 0.3.18 + '@jridgewell/trace-mapping': 0.3.25 '@swc/core': 1.3.7 jest-worker: 27.5.1 - schema-utils: 3.1.1 - serialize-javascript: 6.0.1 - terser: 5.16.9 - webpack: 5.78.0(@swc/core@1.3.7) + schema-utils: 3.3.0 + serialize-javascript: 6.0.2 + terser: 5.29.2 + webpack: 5.90.3(@swc/core@1.3.7) dev: false - /terser-webpack-plugin@5.3.7(@swc/core@1.3.7)(webpack@5.79.0): + /terser-webpack-plugin@5.3.7(@swc/core@1.3.7)(webpack@5.78.0): resolution: {integrity: sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -8270,7 +8532,7 @@ packages: schema-utils: 3.1.1 serialize-javascript: 6.0.1 terser: 5.16.9 - webpack: 5.79.0(@swc/core@1.3.7) + webpack: 5.78.0(@swc/core@1.3.7) dev: false /terser@5.16.9: @@ -8284,6 +8546,17 @@ packages: source-map-support: 0.5.21 dev: false + /terser@5.29.2: + resolution: {integrity: sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.11.3 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: false + /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: false @@ -8343,8 +8616,8 @@ packages: resolution: {integrity: sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==} dev: false - /ts-node@10.9.1(@swc/core@1.3.7)(@types/node@18.15.11)(typescript@5.0.4): - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} + /ts-node@10.9.2(@swc/core@1.3.7)(@types/node@20.11.28)(typescript@5.4.2): + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true peerDependencies: '@swc/core': '>=1.2.50' @@ -8362,15 +8635,15 @@ packages: '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.3 - '@types/node': 18.15.11 - acorn: 8.8.2 - acorn-walk: 8.2.0 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.11.28 + acorn: 8.11.3 + acorn-walk: 8.3.2 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.0.4 + typescript: 5.4.2 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 dev: false @@ -8403,9 +8676,9 @@ packages: is-typedarray: 1.0.0 dev: false - /typescript@5.0.4: - resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} - engines: {node: '>=12.20'} + /typescript@5.4.2: + resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} + engines: {node: '>=14.17'} hasBin: true dev: false @@ -8413,6 +8686,10 @@ packages: resolution: {integrity: sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g==} dev: false + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: false + /unherit@1.1.3: resolution: {integrity: sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==} dependencies: @@ -8544,6 +8821,17 @@ packages: picocolors: 1.0.0 dev: false + /update-browserslist-db@1.0.13(browserslist@4.23.0): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.23.0 + escalade: 3.1.2 + picocolors: 1.0.0 + dev: false + /update-notifier@5.1.0: resolution: {integrity: sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==} engines: {node: '>=10'} @@ -8713,6 +9001,14 @@ packages: graceful-fs: 4.2.11 dev: false + /watchpack@2.4.1: + resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} + engines: {node: '>=10.13.0'} + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + dev: false + /wbuf@1.7.3: resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} dependencies: @@ -8864,8 +9160,8 @@ packages: - uglify-js dev: false - /webpack@5.79.0(@swc/core@1.3.7): - resolution: {integrity: sha512-3mN4rR2Xq+INd6NnYuL9RC9GAmc1ROPKJoHhrZ4pAjdMFEkJJWrsPw8o2JjCIyQyTu7rTXYn4VG6OpyB3CobZg==} + /webpack@5.90.3(@swc/core@1.3.7): + resolution: {integrity: sha512-h6uDYlWCctQRuXBs1oYpVe6sFcWedl0dpcVaTf/YF67J9bKvwJajFulMVSYKHrksMB3I/pIagRzDxwxkebuzKA==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -8874,17 +9170,17 @@ packages: webpack-cli: optional: true dependencies: - '@types/eslint-scope': 3.7.4 - '@types/estree': 1.0.0 - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/wasm-edit': 1.11.1 - '@webassemblyjs/wasm-parser': 1.11.1 - acorn: 8.8.2 - acorn-import-assertions: 1.8.0(acorn@8.8.2) - browserslist: 4.21.5 + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.5 + '@webassemblyjs/ast': 1.12.1 + '@webassemblyjs/wasm-edit': 1.12.1 + '@webassemblyjs/wasm-parser': 1.12.1 + acorn: 8.11.3 + acorn-import-assertions: 1.9.0(acorn@8.11.3) + browserslist: 4.23.0 chrome-trace-event: 1.0.3 - enhanced-resolve: 5.12.0 - es-module-lexer: 1.2.1 + enhanced-resolve: 5.16.0 + es-module-lexer: 1.4.1 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -8893,10 +9189,10 @@ packages: loader-runner: 4.3.0 mime-types: 2.1.35 neo-async: 2.6.2 - schema-utils: 3.1.2 + schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.7(@swc/core@1.3.7)(webpack@5.79.0) - watchpack: 2.4.0 + terser-webpack-plugin: 5.3.10(@swc/core@1.3.7)(webpack@5.90.3) + watchpack: 2.4.1 webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' From 75c0236a046173522d5a18991c3867d54ae9ec59 Mon Sep 17 00:00:00 2001 From: atterpac <89053530+atterpac@users.noreply.github.com> Date: Sat, 16 Mar 2024 20:17:21 -0700 Subject: [PATCH 094/369] [v3] Fix Dev mode processes (#3320) * Fix appimage file sourcing Add findGTKFiles to source webkit files for appimage generation s * Update refresh version to fix CPU usage s * update changelong --- mkdocs-website/docs/en/changelog.md | 3 ++- v3/go.mod | 4 +++- v3/go.sum | 6 ++---- v3/internal/commands/build_assets/devmode.config.tmpl.toml | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/mkdocs-website/docs/en/changelog.md b/mkdocs-website/docs/en/changelog.md index ade4892108d..6b95bd0b998 100644 --- a/mkdocs-website/docs/en/changelog.md +++ b/mkdocs-website/docs/en/changelog.md @@ -18,7 +18,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added - - [darwin] add Event ApplicationShouldHandleReopen to be able to handle dock icon click by @5aaee9 in [#2991](https://github.com/wailsapp/wails/pull/2991) - [darwin] add getPrimaryScreen/getScreens to impl by @tmclane in [#2618](https://github.com/wailsapp/wails/pull/2618) - [darwin] add option for showing the toolbar in fullscreen mode on macOS by [@fbbdev](https://github.com/fbbdev) in [#3282](https://github.com/wailsapp/wails/pull/3282) @@ -30,6 +29,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed zombie processes when working in devmode by updating to latest refresh by [Atterpac](https://github.com/atterpac) in [#3320](https://github.com/wailsapp/wails/pull/3320). +- Fixed appimage webkit file sourcing by [Atterpac](https://github.com/atterpac) in [#3306](https://github.com/wailsapp/wails/pull/3306). - Fixed Doctor apt package verify by [Atterpac](https://github.com/Atterpac) in [#2972](https://github.com/wailsapp/wails/pull/2972). - Fixed application frozen when quit (Darwin) by @5aaee9 in [#2982](https://github.com/wailsapp/wails/pull/2982) - Fixed background colours of examples on Windows by [mmgvh](https://github.com/mmghv) in [#2750](https://github.com/wailsapp/wails/pull/2750). diff --git a/v3/go.mod b/v3/go.mod index 62cbfc35424..229b7ae81e7 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -3,7 +3,7 @@ module github.com/wailsapp/wails/v3 go 1.22 require ( - github.com/atterpac/refresh v0.5.11 + github.com/atterpac/refresh v0.6.2 github.com/bep/debounce v1.2.1 github.com/ebitengine/purego v0.4.0-alpha.4 github.com/go-git/go-git/v5 v5.11.0 @@ -115,3 +115,5 @@ require ( modernc.org/token v1.0.1 // indirect mvdan.cc/sh/v3 v3.7.0 // indirect ) + +replace github.com/wailsapp/wails/v3 => ./ diff --git a/v3/go.sum b/v3/go.sum index 7a60346f0b0..15030fdfa21 100644 --- a/v3/go.sum +++ b/v3/go.sum @@ -62,15 +62,13 @@ github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCv github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= -github.com/alexbrainman/ps v0.0.0-20171229230509-b3e1b4a15894 h1:A6LgNoQeWttVPnIRYzKsbex/HePFxYT9ygCZvgVJDU0= -github.com/alexbrainman/ps v0.0.0-20171229230509-b3e1b4a15894/go.mod h1:Wgrp3f69GNEJz6CdHKtBqKAWdmYTd1K9IlOV+uuv4Uw= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= -github.com/atterpac/refresh v0.5.11 h1:ixFxqR7TCuEGzjFhtt7oHCXD1skhB+Ye59HtIblLRak= -github.com/atterpac/refresh v0.5.11/go.mod h1:IubLmdAVDaTxarKH/AehgJ/QKUtSnawxgvj5HCsIcYo= +github.com/atterpac/refresh v0.6.2 h1:ji/zYIgqi17p+9O8b6PDKRHEfT1WRonYT7P8llIyNAA= +github.com/atterpac/refresh v0.6.2/go.mod h1:IubLmdAVDaTxarKH/AehgJ/QKUtSnawxgvj5HCsIcYo= github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= diff --git a/v3/internal/commands/build_assets/devmode.config.tmpl.toml b/v3/internal/commands/build_assets/devmode.config.tmpl.toml index 09679d26257..06e52bc76af 100644 --- a/v3/internal/commands/build_assets/devmode.config.tmpl.toml +++ b/v3/internal/commands/build_assets/devmode.config.tmpl.toml @@ -1,5 +1,5 @@ [config] -root_path = ".." +root_path = "." # debug | info | warn | error | mute # Defaults to Info if not provided log_level = "warn" @@ -32,4 +32,4 @@ cmd = "KILL_STALE" [[config.executes]] cmd = "./bin/{{.Binary}}" -primary = true \ No newline at end of file +primary = true From bc0a9b2e5228110ac5806bf9d53fbb40ca041060 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 17 Mar 2024 15:08:30 +1100 Subject: [PATCH 095/369] Add `BundledAssetFileServer` for bundled `/wails/runtime.js`. Update examples. --- v3/cmd/wails3/main.go | 1 - v3/examples/binding/assets/index.html | 2 +- v3/examples/binding/main.go | 2 +- v3/examples/contextmenus/assets/index.html | 1 + v3/examples/contextmenus/assets/runtime.js | 1 - v3/examples/contextmenus/main.go | 2 +- v3/examples/dev/main.go | 8 - v3/examples/drag-n-drop/assets/index.html | 1 + v3/examples/drag-n-drop/main.go | 2 +- v3/examples/events/assets/index.html | 2 +- v3/examples/events/assets/runtime.js | 1 - v3/examples/events/main.go | 2 +- v3/examples/frameless/assets/index.html | 2 +- v3/examples/frameless/assets/runtime.js | 1 - v3/examples/frameless/main.go | 2 +- v3/examples/hide-window/main.go | 1 - v3/examples/screen/assets/index.html | 2 +- v3/examples/screen/assets/runtime.js | 1 - v3/examples/screen/main.go | 2 +- v3/examples/window-api/assets/index.html | 2 +- v3/examples/window-api/main.go | 2 +- v3/examples/wml/assets/index.html | 2 +- v3/examples/wml/assets/runtime.js | 1 - v3/examples/wml/main.go | 2 +- v3/go.mod | 1 - .../assetserver/assets/runtime.debug.js | 1139 +++++++++++++++++ v3/internal/assetserver/assets/runtime.js | 1 + .../assetserver/bundled_assetserver.go | 33 + .../bundledassets}/runtime.debug.js | 0 .../assetserver/bundledassets}/runtime.js | 0 .../bundledassets/runtime_dev.go} | 9 +- .../bundledassets/runtime_production.go | 8 + .../build_assets/runtime/runtime.debug.js | 1139 ----------------- .../commands/build_assets/runtime/runtime.js | 1 - v3/internal/commands/runtime.go | 21 - v3/internal/runtime/Taskfile.yaml | 12 +- v3/pkg/application/application.go | 2 +- v3/pkg/application/application_options.go | 9 + v3/pkg/application/assets/alpha/index.html | 2 +- v3/pkg/application/assets/alpha/runtime.js | 1 - 40 files changed, 1214 insertions(+), 1209 deletions(-) delete mode 100644 v3/examples/contextmenus/assets/runtime.js delete mode 100644 v3/examples/events/assets/runtime.js delete mode 100644 v3/examples/frameless/assets/runtime.js delete mode 100644 v3/examples/screen/assets/runtime.js delete mode 100644 v3/examples/wml/assets/runtime.js create mode 100644 v3/internal/assetserver/assets/runtime.debug.js create mode 100644 v3/internal/assetserver/assets/runtime.js create mode 100644 v3/internal/assetserver/bundled_assetserver.go rename v3/{examples/window-api/assets => internal/assetserver/bundledassets}/runtime.debug.js (100%) rename v3/{examples/window-api/assets => internal/assetserver/bundledassets}/runtime.js (100%) rename v3/internal/{commands/build_assets/runtime/compiled.go => assetserver/bundledassets/runtime_dev.go} (51%) create mode 100644 v3/internal/assetserver/bundledassets/runtime_production.go delete mode 100644 v3/internal/commands/build_assets/runtime/runtime.debug.js delete mode 100644 v3/internal/commands/build_assets/runtime/runtime.js delete mode 100644 v3/internal/commands/runtime.go delete mode 100644 v3/pkg/application/assets/alpha/runtime.js diff --git a/v3/cmd/wails3/main.go b/v3/cmd/wails3/main.go index 47e45f12562..34920ae11fc 100644 --- a/v3/cmd/wails3/main.go +++ b/v3/cmd/wails3/main.go @@ -46,7 +46,6 @@ func main() { generate.NewSubCommandFunction("constants", "Generate JS constants from Go", commands.GenerateConstants) generate.NewSubCommandFunction(".desktop", "Generate .desktop file", commands.GenerateDotDesktop) generate.NewSubCommandFunction("appimage", "Generate Linux AppImage", commands.GenerateAppImage) - generate.NewSubCommandFunction("runtime", "Generate the latest compiled runtime", commands.GenerateRuntime) plugin := app.NewSubCommand("plugin", "Plugin tools") //plugin.NewSubCommandFunction("list", "List plugins", commands.PluginList) diff --git a/v3/examples/binding/assets/index.html b/v3/examples/binding/assets/index.html index 7f841393b11..86ec24e487f 100644 --- a/v3/examples/binding/assets/index.html +++ b/v3/examples/binding/assets/index.html @@ -80,7 +80,7 @@ - +

Context Menu Demo

diff --git a/v3/examples/contextmenus/assets/runtime.js b/v3/examples/contextmenus/assets/runtime.js deleted file mode 100644 index baaccee0402..00000000000 --- a/v3/examples/contextmenus/assets/runtime.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return q(Ce,{text:e})}function Me(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/examples/contextmenus/main.go b/v3/examples/contextmenus/main.go index 1a47cb4056b..8aa15d37b23 100644 --- a/v3/examples/contextmenus/main.go +++ b/v3/examples/contextmenus/main.go @@ -17,7 +17,7 @@ func main() { Name: "Context Menu Demo", Description: "A demo of the Context Menu API", Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), + Handler: application.BundledAssetFileServer(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/v3/examples/dev/main.go b/v3/examples/dev/main.go index 478702f5640..f3948061f5c 100644 --- a/v3/examples/dev/main.go +++ b/v3/examples/dev/main.go @@ -35,14 +35,6 @@ func main() { URL: "/", }) - //app.On(events.Common.ThemeChanged, func(e *application.Event) { - // if app.IsDarkMode() { - // log.Println("Dark mode!") - // } else { - // log.Println("Light mode!") - // } - //}) - err := app.Run() if err != nil { diff --git a/v3/examples/drag-n-drop/assets/index.html b/v3/examples/drag-n-drop/assets/index.html index 6e7e2dd5aea..a1bae6db554 100644 --- a/v3/examples/drag-n-drop/assets/index.html +++ b/v3/examples/drag-n-drop/assets/index.html @@ -4,6 +4,7 @@ Title +

Drag-n-drop Demo

diff --git a/v3/examples/drag-n-drop/main.go b/v3/examples/drag-n-drop/main.go index abaaa04a2ed..65dc6dbf2f0 100644 --- a/v3/examples/drag-n-drop/main.go +++ b/v3/examples/drag-n-drop/main.go @@ -18,7 +18,7 @@ func main() { Name: "Drag-n-drop Demo", Description: "A demo of the Drag-n-drop API", Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), + Handler: application.BundledAssetFileServer(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/v3/examples/events/assets/index.html b/v3/examples/events/assets/index.html index a64a42c32da..a1f8f6e246b 100644 --- a/v3/examples/events/assets/index.html +++ b/v3/examples/events/assets/index.html @@ -3,7 +3,7 @@ Title - + diff --git a/v3/examples/events/assets/runtime.js b/v3/examples/events/assets/runtime.js deleted file mode 100644 index ec430090db6..00000000000 --- a/v3/examples/events/assets/runtime.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>Me,Text:()=>xe});var q=l(d.Clipboard,""),Ce=0,Se=1;function Me(e){return q(Ce,{text:e})}function xe(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var M=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",M=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(M=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){M=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return M&&i>0?(h("drag"),!1):M}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,Mi=21,xi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(Mi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(xi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>x,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},x=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,Mn=5,xn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),xn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(Mn,e);function oe(e,i=null){let n=new x(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/examples/events/main.go b/v3/examples/events/main.go index 1fe96a96171..b6bf61bd341 100644 --- a/v3/examples/events/main.go +++ b/v3/examples/events/main.go @@ -19,7 +19,7 @@ func main() { Name: "Events Demo", Description: "A demo of the Events API", Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), + Handler: application.BundledAssetFileServer(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/v3/examples/frameless/assets/index.html b/v3/examples/frameless/assets/index.html index 689c7a2729d..abf63f1e224 100644 --- a/v3/examples/frameless/assets/index.html +++ b/v3/examples/frameless/assets/index.html @@ -20,7 +20,7 @@ padding: 20px; } - +
diff --git a/v3/examples/frameless/assets/runtime.js b/v3/examples/frameless/assets/runtime.js deleted file mode 100644 index baaccee0402..00000000000 --- a/v3/examples/frameless/assets/runtime.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return q(Ce,{text:e})}function Me(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/examples/frameless/main.go b/v3/examples/frameless/main.go index c59b670257e..037ef5de76c 100644 --- a/v3/examples/frameless/main.go +++ b/v3/examples/frameless/main.go @@ -17,7 +17,7 @@ func main() { Name: "Frameless Demo", Description: "A demo of frameless windows", Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), + Handler: application.BundledAssetFileServer(assets), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, diff --git a/v3/examples/hide-window/main.go b/v3/examples/hide-window/main.go index d23ddec7473..8a785d754a8 100644 --- a/v3/examples/hide-window/main.go +++ b/v3/examples/hide-window/main.go @@ -16,7 +16,6 @@ func main() { Description: "A test of Hidden window and display it", Assets: application.AlphaAssets, Mac: application.MacOptions{ - // ActivationPolicy: application.ActivationPolicyAccessory, ApplicationShouldTerminateAfterLastWindowClosed: false, }, }) diff --git a/v3/examples/screen/assets/index.html b/v3/examples/screen/assets/index.html index eafcfe1b9c2..6c628cdd60e 100644 --- a/v3/examples/screen/assets/index.html +++ b/v3/examples/screen/assets/index.html @@ -43,7 +43,7 @@ text-align: -webkit-center; } - + diff --git a/v3/examples/screen/assets/runtime.js b/v3/examples/screen/assets/runtime.js deleted file mode 100644 index baaccee0402..00000000000 --- a/v3/examples/screen/assets/runtime.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return q(Ce,{text:e})}function Me(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/examples/screen/main.go b/v3/examples/screen/main.go index 32c04bafd90..1f9821d29da 100644 --- a/v3/examples/screen/main.go +++ b/v3/examples/screen/main.go @@ -26,7 +26,7 @@ func main() { WebviewBrowserPath: "", }, Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), + Handler: application.BundledAssetFileServer(assets), }, }) diff --git a/v3/examples/window-api/assets/index.html b/v3/examples/window-api/assets/index.html index 29dc32d5be3..d1d3b23609c 100644 --- a/v3/examples/window-api/assets/index.html +++ b/v3/examples/window-api/assets/index.html @@ -129,7 +129,7 @@ font-size: large; } - + - + {var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return q(Ce,{text:e})}function Me(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/examples/wml/main.go b/v3/examples/wml/main.go index aa7a54fb390..32aefa5693b 100644 --- a/v3/examples/wml/main.go +++ b/v3/examples/wml/main.go @@ -20,7 +20,7 @@ func main() { ApplicationShouldTerminateAfterLastWindowClosed: true, }, Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), + Handler: application.BundledAssetFileServer(assets), }, }) diff --git a/v3/go.mod b/v3/go.mod index 229b7ae81e7..a3a8ebcf91b 100644 --- a/v3/go.mod +++ b/v3/go.mod @@ -47,7 +47,6 @@ require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/StackExchange/wmi v1.2.1 // indirect - github.com/alexbrainman/ps v0.0.0-20171229230509-b3e1b4a15894 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/containerd/console v1.0.3 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect diff --git a/v3/internal/assetserver/assets/runtime.debug.js b/v3/internal/assetserver/assets/runtime.debug.js new file mode 100644 index 00000000000..a1da37e3af2 --- /dev/null +++ b/v3/internal/assetserver/assets/runtime.debug.js @@ -0,0 +1,1139 @@ +(() => { + var __defProp = Object.defineProperty; + var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); + }; + + // desktop/@wailsio/runtime/src/log.js + function debugLog(message) { + console.log( + "%c wails3 %c " + message + " ", + "background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem", + "background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem" + ); + } + + // desktop/@wailsio/runtime/src/application.js + var application_exports = {}; + __export(application_exports, { + Hide: () => Hide, + Quit: () => Quit, + Show: () => Show + }); + + // node_modules/nanoid/non-secure/index.js + var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"; + var nanoid = (size2 = 21) => { + let id = ""; + let i = size2; + while (i--) { + id += urlAlphabet[Math.random() * 64 | 0]; + } + return id; + }; + + // desktop/@wailsio/runtime/src/runtime.js + var runtimeURL = window.location.origin + "/wails/runtime"; + var objectNames = { + Call: 0, + Clipboard: 1, + Application: 2, + Events: 3, + ContextMenu: 4, + Dialog: 5, + Window: 6, + Screens: 7, + System: 8, + Browser: 9, + CancelCall: 10 + }; + var clientId = nanoid(); + function newRuntimeCallerWithID(object, windowName) { + return function(method, args = null) { + return runtimeCallWithID(object, method, windowName, args); + }; + } + function runtimeCallWithID(objectID, method, windowName, args) { + let url = new URL(runtimeURL); + url.searchParams.append("object", objectID); + url.searchParams.append("method", method); + let fetchOptions = { + headers: {} + }; + if (windowName) { + fetchOptions.headers["x-wails-window-name"] = windowName; + } + if (args) { + url.searchParams.append("args", JSON.stringify(args)); + } + fetchOptions.headers["x-wails-client-id"] = clientId; + return new Promise((resolve, reject) => { + fetch(url, fetchOptions).then((response) => { + if (response.ok) { + if (response.headers.get("Content-Type") && response.headers.get("Content-Type").indexOf("application/json") !== -1) { + return response.json(); + } else { + return response.text(); + } + } + reject(Error(response.statusText)); + }).then((data) => resolve(data)).catch((error) => reject(error)); + }); + } + + // desktop/@wailsio/runtime/src/application.js + var call = newRuntimeCallerWithID(objectNames.Application, ""); + var HideMethod = 0; + var ShowMethod = 1; + var QuitMethod = 2; + function Hide() { + return call(HideMethod); + } + function Show() { + return call(ShowMethod); + } + function Quit() { + return call(QuitMethod); + } + + // desktop/@wailsio/runtime/src/browser.js + var browser_exports = {}; + __export(browser_exports, { + OpenURL: () => OpenURL + }); + var call2 = newRuntimeCallerWithID(objectNames.Browser, ""); + var BrowserOpenURL = 0; + function OpenURL(url) { + return call2(BrowserOpenURL, { url }); + } + + // desktop/@wailsio/runtime/src/clipboard.js + var clipboard_exports = {}; + __export(clipboard_exports, { + SetText: () => SetText, + Text: () => Text + }); + var call3 = newRuntimeCallerWithID(objectNames.Clipboard, ""); + var ClipboardSetText = 0; + var ClipboardText = 1; + function SetText(text) { + return call3(ClipboardSetText, { text }); + } + function Text() { + return call3(ClipboardText); + } + + // desktop/@wailsio/runtime/src/system.js + var system_exports = {}; + __export(system_exports, { + Capabilities: () => Capabilities, + Environment: () => Environment, + IsAMD64: () => IsAMD64, + IsARM: () => IsARM, + IsARM64: () => IsARM64, + IsDarkMode: () => IsDarkMode, + IsDebug: () => IsDebug, + IsLinux: () => IsLinux, + IsMac: () => IsMac, + IsWindows: () => IsWindows, + invoke: () => invoke + }); + var call4 = newRuntimeCallerWithID(objectNames.System, ""); + var systemIsDarkMode = 0; + var environment = 1; + function invoke(msg) { + if (window.chrome) { + return window.chrome.webview.postMessage(msg); + } + return window.webkit.messageHandlers.external.postMessage(msg); + } + function IsDarkMode() { + return call4(systemIsDarkMode); + } + function Capabilities() { + let response = fetch("/wails/capabilities"); + return response.json(); + } + function Environment() { + return call4(environment); + } + function IsWindows() { + return window._wails.environment.OS === "windows"; + } + function IsLinux() { + return window._wails.environment.OS === "linux"; + } + function IsMac() { + return window._wails.environment.OS === "darwin"; + } + function IsAMD64() { + return window._wails.environment.Arch === "amd64"; + } + function IsARM() { + return window._wails.environment.Arch === "arm"; + } + function IsARM64() { + return window._wails.environment.Arch === "arm64"; + } + function IsDebug() { + return window._wails.environment.Debug === true; + } + + // desktop/@wailsio/runtime/src/contextmenu.js + window.addEventListener("contextmenu", contextMenuHandler); + var call5 = newRuntimeCallerWithID(objectNames.ContextMenu, ""); + var ContextMenuOpen = 0; + function openContextMenu(id, x, y, data) { + void call5(ContextMenuOpen, { id, x, y, data }); + } + function contextMenuHandler(event) { + let element = event.target; + let customContextMenu = window.getComputedStyle(element).getPropertyValue("--custom-contextmenu"); + customContextMenu = customContextMenu ? customContextMenu.trim() : ""; + if (customContextMenu) { + event.preventDefault(); + let customContextMenuData = window.getComputedStyle(element).getPropertyValue("--custom-contextmenu-data"); + openContextMenu(customContextMenu, event.clientX, event.clientY, customContextMenuData); + return; + } + processDefaultContextMenu(event); + } + function processDefaultContextMenu(event) { + if (IsDebug()) { + return; + } + const element = event.target; + const computedStyle = window.getComputedStyle(element); + const defaultContextMenuAction = computedStyle.getPropertyValue("--default-contextmenu").trim(); + switch (defaultContextMenuAction) { + case "show": + return; + case "hide": + event.preventDefault(); + return; + default: + if (element.isContentEditable) { + return; + } + const selection = window.getSelection(); + const hasSelection = selection.toString().length > 0; + if (hasSelection) { + for (let i = 0; i < selection.rangeCount; i++) { + const range = selection.getRangeAt(i); + const rects = range.getClientRects(); + for (let j = 0; j < rects.length; j++) { + const rect = rects[j]; + if (document.elementFromPoint(rect.left, rect.top) === element) { + return; + } + } + } + } + if (element.tagName === "INPUT" || element.tagName === "TEXTAREA") { + if (hasSelection || !element.readOnly && !element.disabled) { + return; + } + } + event.preventDefault(); + } + } + + // desktop/@wailsio/runtime/src/flags.js + var flags_exports = {}; + __export(flags_exports, { + GetFlag: () => GetFlag + }); + function GetFlag(keyString) { + try { + return window._wails.flags[keyString]; + } catch (e) { + throw new Error("Unable to retrieve flag '" + keyString + "': " + e); + } + } + + // desktop/@wailsio/runtime/src/drag.js + window._wails = window._wails || {}; + window._wails.setResizable = setResizable; + window._wails.endDrag = endDrag; + window.addEventListener("mousedown", onMouseDown); + window.addEventListener("mousemove", onMouseMove); + window.addEventListener("mouseup", onMouseUp); + var shouldDrag = false; + var resizeEdge = null; + var resizable = false; + var defaultCursor = "auto"; + function dragTest(e) { + let val = window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region"); + if (!val || val === "" || val.trim() !== "drag" || e.buttons !== 1) { + return false; + } + return e.detail === 1; + } + function setResizable(value) { + resizable = value; + } + function endDrag() { + document.body.style.cursor = "default"; + shouldDrag = false; + } + function testResize() { + if (resizeEdge) { + invoke(`resize:${resizeEdge}`); + return true; + } + return false; + } + function onMouseDown(e) { + if (IsWindows() && testResize() || dragTest(e)) { + shouldDrag = !!isValidDrag(e); + } + } + function isValidDrag(e) { + return !(e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight); + } + function onMouseUp(e) { + let mousePressed = e.buttons !== void 0 ? e.buttons : e.which; + if (mousePressed > 0) { + endDrag(); + } + } + function setResize(cursor = defaultCursor) { + document.documentElement.style.cursor = cursor; + resizeEdge = cursor; + } + function onMouseMove(e) { + shouldDrag = checkDrag(e); + if (IsWindows() && resizable) { + handleResize(e); + } + } + function checkDrag(e) { + let mousePressed = e.buttons !== void 0 ? e.buttons : e.which; + if (shouldDrag && mousePressed > 0) { + invoke("drag"); + return false; + } + return shouldDrag; + } + function handleResize(e) { + let resizeHandleHeight = GetFlag("system.resizeHandleHeight") || 5; + let resizeHandleWidth = GetFlag("system.resizeHandleWidth") || 5; + let cornerExtra = GetFlag("resizeCornerExtra") || 10; + let rightBorder = window.outerWidth - e.clientX < resizeHandleWidth; + let leftBorder = e.clientX < resizeHandleWidth; + let topBorder = e.clientY < resizeHandleHeight; + let bottomBorder = window.outerHeight - e.clientY < resizeHandleHeight; + let rightCorner = window.outerWidth - e.clientX < resizeHandleWidth + cornerExtra; + let leftCorner = e.clientX < resizeHandleWidth + cornerExtra; + let topCorner = e.clientY < resizeHandleHeight + cornerExtra; + let bottomCorner = window.outerHeight - e.clientY < resizeHandleHeight + cornerExtra; + if (!leftBorder && !rightBorder && !topBorder && !bottomBorder && resizeEdge !== void 0) { + setResize(); + } else if (rightCorner && bottomCorner) + setResize("se-resize"); + else if (leftCorner && bottomCorner) + setResize("sw-resize"); + else if (leftCorner && topCorner) + setResize("nw-resize"); + else if (topCorner && rightCorner) + setResize("ne-resize"); + else if (leftBorder) + setResize("w-resize"); + else if (topBorder) + setResize("n-resize"); + else if (bottomBorder) + setResize("s-resize"); + else if (rightBorder) + setResize("e-resize"); + } + + // desktop/@wailsio/runtime/src/screens.js + var screens_exports = {}; + __export(screens_exports, { + GetAll: () => GetAll, + GetCurrent: () => GetCurrent, + GetPrimary: () => GetPrimary + }); + var call6 = newRuntimeCallerWithID(objectNames.Screens, ""); + var getAll = 0; + var getPrimary = 1; + var getCurrent = 2; + function GetAll() { + return call6(getAll); + } + function GetPrimary() { + return call6(getPrimary); + } + function GetCurrent() { + return call6(getCurrent); + } + + // desktop/@wailsio/runtime/src/window.js + var window_exports = {}; + __export(window_exports, { + Center: () => Center, + Close: () => Close, + Fullscreen: () => Fullscreen, + Get: () => Get, + GetZoomLevel: () => GetZoomLevel, + Height: () => Height, + Hide: () => Hide2, + Maximise: () => Maximise, + Minimise: () => Minimise, + RelativePosition: () => RelativePosition, + Restore: () => Restore, + Screen: () => Screen, + SetAlwaysOnTop: () => SetAlwaysOnTop, + SetBackgroundColour: () => SetBackgroundColour, + SetMaxSize: () => SetMaxSize, + SetMinSize: () => SetMinSize, + SetRelativePosition: () => SetRelativePosition, + SetResizable: () => SetResizable, + SetSize: () => SetSize, + SetTitle: () => SetTitle, + SetZoomLevel: () => SetZoomLevel, + Show: () => Show2, + Size: () => Size, + ToggleMaximise: () => ToggleMaximise, + UnMaximise: () => UnMaximise, + UnMinimise: () => UnMinimise, + Width: () => Width, + ZoomIn: () => ZoomIn, + ZoomOut: () => ZoomOut, + ZoomReset: () => ZoomReset + }); + var center = 0; + var setTitle = 1; + var fullscreen = 2; + var unFullscreen = 3; + var setSize = 4; + var size = 5; + var setMaxSize = 6; + var setMinSize = 7; + var setAlwaysOnTop = 8; + var setRelativePosition = 9; + var relativePosition = 10; + var screen = 11; + var hide = 12; + var maximise = 13; + var unMaximise = 14; + var toggleMaximise = 15; + var minimise = 16; + var unMinimise = 17; + var restore = 18; + var show = 19; + var close = 20; + var setBackgroundColour = 21; + var setResizable2 = 22; + var width = 23; + var height = 24; + var zoomIn = 25; + var zoomOut = 26; + var zoomReset = 27; + var getZoomLevel = 28; + var setZoomLevel = 29; + var thisWindow = Get(""); + function createWindow(call10) { + return { + Get: (windowName) => createWindow(newRuntimeCallerWithID(objectNames.Window, windowName)), + Center: () => call10(center), + SetTitle: (title) => call10(setTitle, { title }), + Fullscreen: () => call10(fullscreen), + UnFullscreen: () => call10(unFullscreen), + SetSize: (width2, height2) => call10(setSize, { width: width2, height: height2 }), + Size: () => call10(size), + SetMaxSize: (width2, height2) => call10(setMaxSize, { width: width2, height: height2 }), + SetMinSize: (width2, height2) => call10(setMinSize, { width: width2, height: height2 }), + SetAlwaysOnTop: (onTop) => call10(setAlwaysOnTop, { alwaysOnTop: onTop }), + SetRelativePosition: (x, y) => call10(setRelativePosition, { x, y }), + RelativePosition: () => call10(relativePosition), + Screen: () => call10(screen), + Hide: () => call10(hide), + Maximise: () => call10(maximise), + UnMaximise: () => call10(unMaximise), + ToggleMaximise: () => call10(toggleMaximise), + Minimise: () => call10(minimise), + UnMinimise: () => call10(unMinimise), + Restore: () => call10(restore), + Show: () => call10(show), + Close: () => call10(close), + SetBackgroundColour: (r, g, b, a) => call10(setBackgroundColour, { r, g, b, a }), + SetResizable: (resizable2) => call10(setResizable2, { resizable: resizable2 }), + Width: () => call10(width), + Height: () => call10(height), + ZoomIn: () => call10(zoomIn), + ZoomOut: () => call10(zoomOut), + ZoomReset: () => call10(zoomReset), + GetZoomLevel: () => call10(getZoomLevel), + SetZoomLevel: (zoomLevel) => call10(setZoomLevel, { zoomLevel }) + }; + } + function Get(windowName) { + return createWindow(newRuntimeCallerWithID(objectNames.Window, windowName)); + } + function Center() { + thisWindow.Center(); + } + function SetTitle(title) { + thisWindow.SetTitle(title); + } + function Fullscreen() { + thisWindow.Fullscreen(); + } + function SetSize(width2, height2) { + thisWindow.SetSize(width2, height2); + } + function Size() { + return thisWindow.Size(); + } + function SetMaxSize(width2, height2) { + thisWindow.SetMaxSize(width2, height2); + } + function SetMinSize(width2, height2) { + thisWindow.SetMinSize(width2, height2); + } + function SetAlwaysOnTop(onTop) { + thisWindow.SetAlwaysOnTop(onTop); + } + function SetRelativePosition(x, y) { + thisWindow.SetRelativePosition(x, y); + } + function RelativePosition() { + return thisWindow.RelativePosition(); + } + function Screen() { + return thisWindow.Screen(); + } + function Hide2() { + thisWindow.Hide(); + } + function Maximise() { + thisWindow.Maximise(); + } + function UnMaximise() { + thisWindow.UnMaximise(); + } + function ToggleMaximise() { + thisWindow.ToggleMaximise(); + } + function Minimise() { + thisWindow.Minimise(); + } + function UnMinimise() { + thisWindow.UnMinimise(); + } + function Restore() { + thisWindow.Restore(); + } + function Show2() { + thisWindow.Show(); + } + function Close() { + thisWindow.Close(); + } + function SetBackgroundColour(r, g, b, a) { + thisWindow.SetBackgroundColour(r, g, b, a); + } + function SetResizable(resizable2) { + thisWindow.SetResizable(resizable2); + } + function Width() { + return thisWindow.Width(); + } + function Height() { + return thisWindow.Height(); + } + function ZoomIn() { + thisWindow.ZoomIn(); + } + function ZoomOut() { + thisWindow.ZoomOut(); + } + function ZoomReset() { + thisWindow.ZoomReset(); + } + function GetZoomLevel() { + return thisWindow.GetZoomLevel(); + } + function SetZoomLevel(zoomLevel) { + thisWindow.SetZoomLevel(zoomLevel); + } + + // desktop/@wailsio/runtime/src/wml.js + var wml_exports = {}; + __export(wml_exports, { + Reload: () => Reload + }); + + // desktop/@wailsio/runtime/src/events.js + var events_exports = {}; + __export(events_exports, { + Emit: () => Emit, + Off: () => Off, + OffAll: () => OffAll, + On: () => On, + OnMultiple: () => OnMultiple, + Once: () => Once, + Types: () => Types, + WailsEvent: () => WailsEvent, + setup: () => setup + }); + + // desktop/@wailsio/runtime/src/event_types.js + var EventTypes = { + Windows: { + SystemThemeChanged: "windows:SystemThemeChanged", + APMPowerStatusChange: "windows:APMPowerStatusChange", + APMSuspend: "windows:APMSuspend", + APMResumeAutomatic: "windows:APMResumeAutomatic", + APMResumeSuspend: "windows:APMResumeSuspend", + APMPowerSettingChange: "windows:APMPowerSettingChange", + ApplicationStarted: "windows:ApplicationStarted", + WebViewNavigationCompleted: "windows:WebViewNavigationCompleted", + WindowInactive: "windows:WindowInactive", + WindowActive: "windows:WindowActive", + WindowClickActive: "windows:WindowClickActive", + WindowMaximise: "windows:WindowMaximise", + WindowUnMaximise: "windows:WindowUnMaximise", + WindowFullscreen: "windows:WindowFullscreen", + WindowUnFullscreen: "windows:WindowUnFullscreen", + WindowRestore: "windows:WindowRestore", + WindowMinimise: "windows:WindowMinimise", + WindowUnMinimise: "windows:WindowUnMinimise", + WindowClose: "windows:WindowClose", + WindowSetFocus: "windows:WindowSetFocus", + WindowKillFocus: "windows:WindowKillFocus", + WindowDragDrop: "windows:WindowDragDrop", + WindowDragEnter: "windows:WindowDragEnter", + WindowDragLeave: "windows:WindowDragLeave", + WindowDragOver: "windows:WindowDragOver" + }, + Mac: { + ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive", + ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties", + ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance", + ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon", + ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState", + ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters", + ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame", + ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation", + ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", + ApplicationDidHide: "mac:ApplicationDidHide", + ApplicationDidResignActiveNotification: "mac:ApplicationDidResignActiveNotification", + ApplicationDidUnhide: "mac:ApplicationDidUnhide", + ApplicationDidUpdate: "mac:ApplicationDidUpdate", + ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive", + ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching", + ApplicationWillHide: "mac:ApplicationWillHide", + ApplicationWillResignActive: "mac:ApplicationWillResignActive", + ApplicationWillTerminate: "mac:ApplicationWillTerminate", + ApplicationWillUnhide: "mac:ApplicationWillUnhide", + ApplicationWillUpdate: "mac:ApplicationWillUpdate", + ApplicationDidChangeTheme: "mac:ApplicationDidChangeTheme!", + ApplicationShouldHandleReopen: "mac:ApplicationShouldHandleReopen!", + WindowDidBecomeKey: "mac:WindowDidBecomeKey", + WindowDidBecomeMain: "mac:WindowDidBecomeMain", + WindowDidBeginSheet: "mac:WindowDidBeginSheet", + WindowDidChangeAlpha: "mac:WindowDidChangeAlpha", + WindowDidChangeBackingLocation: "mac:WindowDidChangeBackingLocation", + WindowDidChangeBackingProperties: "mac:WindowDidChangeBackingProperties", + WindowDidChangeCollectionBehavior: "mac:WindowDidChangeCollectionBehavior", + WindowDidChangeEffectiveAppearance: "mac:WindowDidChangeEffectiveAppearance", + WindowDidChangeOcclusionState: "mac:WindowDidChangeOcclusionState", + WindowDidChangeOrderingMode: "mac:WindowDidChangeOrderingMode", + WindowDidChangeScreen: "mac:WindowDidChangeScreen", + WindowDidChangeScreenParameters: "mac:WindowDidChangeScreenParameters", + WindowDidChangeScreenProfile: "mac:WindowDidChangeScreenProfile", + WindowDidChangeScreenSpace: "mac:WindowDidChangeScreenSpace", + WindowDidChangeScreenSpaceProperties: "mac:WindowDidChangeScreenSpaceProperties", + WindowDidChangeSharingType: "mac:WindowDidChangeSharingType", + WindowDidChangeSpace: "mac:WindowDidChangeSpace", + WindowDidChangeSpaceOrderingMode: "mac:WindowDidChangeSpaceOrderingMode", + WindowDidChangeTitle: "mac:WindowDidChangeTitle", + WindowDidChangeToolbar: "mac:WindowDidChangeToolbar", + WindowDidChangeVisibility: "mac:WindowDidChangeVisibility", + WindowDidDeminiaturize: "mac:WindowDidDeminiaturize", + WindowDidEndSheet: "mac:WindowDidEndSheet", + WindowDidEnterFullScreen: "mac:WindowDidEnterFullScreen", + WindowDidEnterVersionBrowser: "mac:WindowDidEnterVersionBrowser", + WindowDidExitFullScreen: "mac:WindowDidExitFullScreen", + WindowDidExitVersionBrowser: "mac:WindowDidExitVersionBrowser", + WindowDidExpose: "mac:WindowDidExpose", + WindowDidFocus: "mac:WindowDidFocus", + WindowDidMiniaturize: "mac:WindowDidMiniaturize", + WindowDidMove: "mac:WindowDidMove", + WindowDidOrderOffScreen: "mac:WindowDidOrderOffScreen", + WindowDidOrderOnScreen: "mac:WindowDidOrderOnScreen", + WindowDidResignKey: "mac:WindowDidResignKey", + WindowDidResignMain: "mac:WindowDidResignMain", + WindowDidResize: "mac:WindowDidResize", + WindowDidUpdate: "mac:WindowDidUpdate", + WindowDidUpdateAlpha: "mac:WindowDidUpdateAlpha", + WindowDidUpdateCollectionBehavior: "mac:WindowDidUpdateCollectionBehavior", + WindowDidUpdateCollectionProperties: "mac:WindowDidUpdateCollectionProperties", + WindowDidUpdateShadow: "mac:WindowDidUpdateShadow", + WindowDidUpdateTitle: "mac:WindowDidUpdateTitle", + WindowDidUpdateToolbar: "mac:WindowDidUpdateToolbar", + WindowDidUpdateVisibility: "mac:WindowDidUpdateVisibility", + WindowShouldClose: "mac:WindowShouldClose!", + WindowWillBecomeKey: "mac:WindowWillBecomeKey", + WindowWillBecomeMain: "mac:WindowWillBecomeMain", + WindowWillBeginSheet: "mac:WindowWillBeginSheet", + WindowWillChangeOrderingMode: "mac:WindowWillChangeOrderingMode", + WindowWillClose: "mac:WindowWillClose", + WindowWillDeminiaturize: "mac:WindowWillDeminiaturize", + WindowWillEnterFullScreen: "mac:WindowWillEnterFullScreen", + WindowWillEnterVersionBrowser: "mac:WindowWillEnterVersionBrowser", + WindowWillExitFullScreen: "mac:WindowWillExitFullScreen", + WindowWillExitVersionBrowser: "mac:WindowWillExitVersionBrowser", + WindowWillFocus: "mac:WindowWillFocus", + WindowWillMiniaturize: "mac:WindowWillMiniaturize", + WindowWillMove: "mac:WindowWillMove", + WindowWillOrderOffScreen: "mac:WindowWillOrderOffScreen", + WindowWillOrderOnScreen: "mac:WindowWillOrderOnScreen", + WindowWillResignMain: "mac:WindowWillResignMain", + WindowWillResize: "mac:WindowWillResize", + WindowWillUnfocus: "mac:WindowWillUnfocus", + WindowWillUpdate: "mac:WindowWillUpdate", + WindowWillUpdateAlpha: "mac:WindowWillUpdateAlpha", + WindowWillUpdateCollectionBehavior: "mac:WindowWillUpdateCollectionBehavior", + WindowWillUpdateCollectionProperties: "mac:WindowWillUpdateCollectionProperties", + WindowWillUpdateShadow: "mac:WindowWillUpdateShadow", + WindowWillUpdateTitle: "mac:WindowWillUpdateTitle", + WindowWillUpdateToolbar: "mac:WindowWillUpdateToolbar", + WindowWillUpdateVisibility: "mac:WindowWillUpdateVisibility", + WindowWillUseStandardFrame: "mac:WindowWillUseStandardFrame", + MenuWillOpen: "mac:MenuWillOpen", + MenuDidOpen: "mac:MenuDidOpen", + MenuDidClose: "mac:MenuDidClose", + MenuWillSendAction: "mac:MenuWillSendAction", + MenuDidSendAction: "mac:MenuDidSendAction", + MenuWillHighlightItem: "mac:MenuWillHighlightItem", + MenuDidHighlightItem: "mac:MenuDidHighlightItem", + MenuWillDisplayItem: "mac:MenuWillDisplayItem", + MenuDidDisplayItem: "mac:MenuDidDisplayItem", + MenuWillAddItem: "mac:MenuWillAddItem", + MenuDidAddItem: "mac:MenuDidAddItem", + MenuWillRemoveItem: "mac:MenuWillRemoveItem", + MenuDidRemoveItem: "mac:MenuDidRemoveItem", + MenuWillBeginTracking: "mac:MenuWillBeginTracking", + MenuDidBeginTracking: "mac:MenuDidBeginTracking", + MenuWillEndTracking: "mac:MenuWillEndTracking", + MenuDidEndTracking: "mac:MenuDidEndTracking", + MenuWillUpdate: "mac:MenuWillUpdate", + MenuDidUpdate: "mac:MenuDidUpdate", + MenuWillPopUp: "mac:MenuWillPopUp", + MenuDidPopUp: "mac:MenuDidPopUp", + MenuWillSendActionToItem: "mac:MenuWillSendActionToItem", + MenuDidSendActionToItem: "mac:MenuDidSendActionToItem", + WebViewDidStartProvisionalNavigation: "mac:WebViewDidStartProvisionalNavigation", + WebViewDidReceiveServerRedirectForProvisionalNavigation: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation", + WebViewDidFinishNavigation: "mac:WebViewDidFinishNavigation", + WebViewDidCommitNavigation: "mac:WebViewDidCommitNavigation", + WindowFileDraggingEntered: "mac:WindowFileDraggingEntered", + WindowFileDraggingPerformed: "mac:WindowFileDraggingPerformed", + WindowFileDraggingExited: "mac:WindowFileDraggingExited" + }, + Linux: { + SystemThemeChanged: "linux:SystemThemeChanged", + WindowLoadChanged: "linux:WindowLoadChanged", + WindowDeleteEvent: "linux:WindowDeleteEvent", + WindowFocusIn: "linux:WindowFocusIn", + WindowFocusOut: "linux:WindowFocusOut", + ApplicationStartup: "linux:ApplicationStartup" + }, + Common: { + ApplicationStarted: "common:ApplicationStarted", + WindowMaximise: "common:WindowMaximise", + WindowUnMaximise: "common:WindowUnMaximise", + WindowFullscreen: "common:WindowFullscreen", + WindowUnFullscreen: "common:WindowUnFullscreen", + WindowRestore: "common:WindowRestore", + WindowMinimise: "common:WindowMinimise", + WindowUnMinimise: "common:WindowUnMinimise", + WindowClosing: "common:WindowClosing", + WindowZoom: "common:WindowZoom", + WindowZoomIn: "common:WindowZoomIn", + WindowZoomOut: "common:WindowZoomOut", + WindowZoomReset: "common:WindowZoomReset", + WindowFocus: "common:WindowFocus", + WindowLostFocus: "common:WindowLostFocus", + WindowShow: "common:WindowShow", + WindowHide: "common:WindowHide", + WindowDPIChanged: "common:WindowDPIChanged", + WindowFilesDropped: "common:WindowFilesDropped", + WindowRuntimeReady: "common:WindowRuntimeReady", + ThemeChanged: "common:ThemeChanged" + } + }; + + // desktop/@wailsio/runtime/src/events.js + var Types = EventTypes; + window._wails = window._wails || {}; + window._wails.dispatchWailsEvent = dispatchWailsEvent; + var call7 = newRuntimeCallerWithID(objectNames.Events, ""); + var EmitMethod = 0; + var eventListeners = /* @__PURE__ */ new Map(); + var Listener = class { + constructor(eventName, callback, maxCallbacks) { + this.eventName = eventName; + this.maxCallbacks = maxCallbacks || -1; + this.Callback = (data) => { + callback(data); + if (this.maxCallbacks === -1) + return false; + this.maxCallbacks -= 1; + return this.maxCallbacks === 0; + }; + } + }; + var WailsEvent = class { + constructor(name, data = null) { + this.name = name; + this.data = data; + } + }; + function setup() { + } + function dispatchWailsEvent(event) { + let listeners = eventListeners.get(event.name); + if (listeners) { + let toRemove = listeners.filter((listener) => { + let remove = listener.Callback(event); + if (remove) + return true; + }); + if (toRemove.length > 0) { + listeners = listeners.filter((l) => !toRemove.includes(l)); + if (listeners.length === 0) + eventListeners.delete(event.name); + else + eventListeners.set(event.name, listeners); + } + } + } + function OnMultiple(eventName, callback, maxCallbacks) { + let listeners = eventListeners.get(eventName) || []; + const thisListener = new Listener(eventName, callback, maxCallbacks); + listeners.push(thisListener); + eventListeners.set(eventName, listeners); + return () => listenerOff(thisListener); + } + function On(eventName, callback) { + return OnMultiple(eventName, callback, -1); + } + function Once(eventName, callback) { + return OnMultiple(eventName, callback, 1); + } + function listenerOff(listener) { + const eventName = listener.eventName; + let listeners = eventListeners.get(eventName).filter((l) => l !== listener); + if (listeners.length === 0) + eventListeners.delete(eventName); + else + eventListeners.set(eventName, listeners); + } + function Off(eventName, ...additionalEventNames) { + let eventsToRemove = [eventName, ...additionalEventNames]; + eventsToRemove.forEach((eventName2) => eventListeners.delete(eventName2)); + } + function OffAll() { + eventListeners.clear(); + } + function Emit(event) { + return call7(EmitMethod, event); + } + + // desktop/@wailsio/runtime/src/dialogs.js + var dialogs_exports = {}; + __export(dialogs_exports, { + Error: () => Error2, + Info: () => Info, + OpenFile: () => OpenFile, + Question: () => Question, + SaveFile: () => SaveFile, + Warning: () => Warning + }); + window._wails = window._wails || {}; + window._wails.dialogErrorCallback = dialogErrorCallback; + window._wails.dialogResultCallback = dialogResultCallback; + var DialogInfo = 0; + var DialogWarning = 1; + var DialogError = 2; + var DialogQuestion = 3; + var DialogOpenFile = 4; + var DialogSaveFile = 5; + var call8 = newRuntimeCallerWithID(objectNames.Dialog, ""); + var dialogResponses = /* @__PURE__ */ new Map(); + function generateID() { + let result; + do { + result = nanoid(); + } while (dialogResponses.has(result)); + return result; + } + function dialog(type, options = {}) { + const id = generateID(); + options["dialog-id"] = id; + return new Promise((resolve, reject) => { + dialogResponses.set(id, { resolve, reject }); + call8(type, options).catch((error) => { + reject(error); + dialogResponses.delete(id); + }); + }); + } + function dialogResultCallback(id, data, isJSON) { + let p = dialogResponses.get(id); + if (p) { + if (isJSON) { + p.resolve(JSON.parse(data)); + } else { + p.resolve(data); + } + dialogResponses.delete(id); + } + } + function dialogErrorCallback(id, message) { + let p = dialogResponses.get(id); + if (p) { + p.reject(message); + dialogResponses.delete(id); + } + } + var Info = (options) => dialog(DialogInfo, options); + var Warning = (options) => dialog(DialogWarning, options); + var Error2 = (options) => dialog(DialogError, options); + var Question = (options) => dialog(DialogQuestion, options); + var OpenFile = (options) => dialog(DialogOpenFile, options); + var SaveFile = (options) => dialog(DialogSaveFile, options); + + // desktop/@wailsio/runtime/src/wml.js + function sendEvent(eventName, data = null) { + let event = new WailsEvent(eventName, data); + Emit(event); + } + function addWMLEventListeners() { + const elements = document.querySelectorAll("[wml-event]"); + elements.forEach(function(element) { + const eventType = element.getAttribute("wml-event"); + const confirm = element.getAttribute("wml-confirm"); + const trigger = element.getAttribute("wml-trigger") || "click"; + let callback = function() { + if (confirm) { + Question({ Title: "Confirm", Message: confirm, Detached: false, Buttons: [{ Label: "Yes" }, { Label: "No", IsDefault: true }] }).then(function(result) { + if (result !== "No") { + sendEvent(eventType); + } + }); + return; + } + sendEvent(eventType); + }; + element.removeEventListener(trigger, callback); + element.addEventListener(trigger, callback); + }); + } + function callWindowMethod(windowName, method) { + let targetWindow = Get(windowName); + let methodMap = WindowMethods(targetWindow); + if (!methodMap.has(method)) { + console.log("Window method " + method + " not found"); + } + try { + methodMap.get(method)(); + } catch (e) { + console.error("Error calling window method '" + method + "': " + e); + } + } + function addWMLWindowListeners() { + const elements = document.querySelectorAll("[wml-window]"); + elements.forEach(function(element) { + const windowMethod = element.getAttribute("wml-window"); + const confirm = element.getAttribute("wml-confirm"); + const trigger = element.getAttribute("wml-trigger") || "click"; + const targetWindow = element.getAttribute("wml-target-window") || ""; + let callback = function() { + if (confirm) { + Question({ Title: "Confirm", Message: confirm, Buttons: [{ Label: "Yes" }, { Label: "No", IsDefault: true }] }).then(function(result) { + if (result !== "No") { + callWindowMethod(targetWindow, windowMethod); + } + }); + return; + } + callWindowMethod(targetWindow, windowMethod); + }; + element.removeEventListener(trigger, callback); + element.addEventListener(trigger, callback); + }); + } + function addWMLOpenBrowserListener() { + const elements = document.querySelectorAll("[wml-openurl]"); + elements.forEach(function(element) { + const url = element.getAttribute("wml-openurl"); + const confirm = element.getAttribute("wml-confirm"); + const trigger = element.getAttribute("wml-trigger") || "click"; + let callback = function() { + if (confirm) { + Question({ Title: "Confirm", Message: confirm, Buttons: [{ Label: "Yes" }, { Label: "No", IsDefault: true }] }).then(function(result) { + if (result !== "No") { + void OpenURL(url); + } + }); + return; + } + void OpenURL(url); + }; + element.removeEventListener(trigger, callback); + element.addEventListener(trigger, callback); + }); + } + function Reload() { + addWMLEventListeners(); + addWMLWindowListeners(); + addWMLOpenBrowserListener(); + } + function WindowMethods(targetWindow) { + let result = /* @__PURE__ */ new Map(); + for (let method in targetWindow) { + if (typeof targetWindow[method] === "function") { + result.set(method, targetWindow[method]); + } + } + return result; + } + + // desktop/@wailsio/runtime/src/calls.js + var calls_exports = {}; + __export(calls_exports, { + ByID: () => ByID, + ByName: () => ByName, + Call: () => Call, + Plugin: () => Plugin + }); + window._wails = window._wails || {}; + window._wails.callResultHandler = resultHandler; + window._wails.callErrorHandler = errorHandler; + var CallBinding = 0; + var call9 = newRuntimeCallerWithID(objectNames.Call, ""); + var cancelCall = newRuntimeCallerWithID(objectNames.CancelCall, ""); + var callResponses = /* @__PURE__ */ new Map(); + function generateID2() { + let result; + do { + result = nanoid(); + } while (callResponses.has(result)); + return result; + } + function resultHandler(id, data, isJSON) { + const promiseHandler = getAndDeleteResponse(id); + if (promiseHandler) { + promiseHandler.resolve(isJSON ? JSON.parse(data) : data); + } + } + function errorHandler(id, message) { + const promiseHandler = getAndDeleteResponse(id); + if (promiseHandler) { + promiseHandler.reject(message); + } + } + function getAndDeleteResponse(id) { + const response = callResponses.get(id); + callResponses.delete(id); + return response; + } + function callBinding(type, options = {}) { + const id = generateID2(); + const doCancel = () => { + cancelCall(type, { "call-id": id }); + }; + var queuedCancel = false, callRunning = false; + var p = new Promise((resolve, reject) => { + options["call-id"] = id; + callResponses.set(id, { resolve, reject }); + call9(type, options).then((_) => { + callRunning = true; + if (queuedCancel) { + doCancel(); + } + }).catch((error) => { + reject(error); + callResponses.delete(id); + }); + }); + p.cancel = () => { + if (callRunning) { + doCancel(); + } else { + queuedCancel = true; + } + }; + return p; + } + function Call(options) { + return callBinding(CallBinding, options); + } + function ByName(name, ...args) { + if (typeof name !== "string" || name.split(".").length !== 3) { + throw new Error("CallByName requires a string in the format 'package.struct.method'"); + } + let [packageName, structName, methodName] = name.split("."); + return callBinding(CallBinding, { + packageName, + structName, + methodName, + args + }); + } + function ByID(methodID, ...args) { + return callBinding(CallBinding, { + methodID, + args + }); + } + function Plugin(pluginName, methodName, ...args) { + return callBinding(CallBinding, { + packageName: "wails-plugins", + structName: pluginName, + methodName, + args + }); + } + + // desktop/compiled/main.js + window._wails = window._wails || {}; + window._wails.invoke = invoke; + window.wails = window.wails || {}; + window.wails.Application = application_exports; + window.wails.Browser = browser_exports; + window.wails.Call = calls_exports; + window.wails.Clipboard = clipboard_exports; + window.wails.Dialogs = dialogs_exports; + window.wails.Events = events_exports; + window.wails.Flags = flags_exports; + window.wails.Screens = screens_exports; + window.wails.System = system_exports; + window.wails.Window = window_exports; + window.wails.WML = wml_exports; + var isReady = false; + document.addEventListener("DOMContentLoaded", function() { + isReady = true; + window._wails.invoke("wails:runtime:ready"); + if (true) { + debugLog("Wails Runtime Loaded"); + } + }); + function whenReady(fn) { + if (isReady || document.readyState === "complete") { + fn(); + } else { + document.addEventListener("DOMContentLoaded", fn); + } + } + whenReady(() => { + Reload(); + }); +})(); +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZy5qcyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb24uanMiLCAiLi4vLi4vcnVudGltZS9ub2RlX21vZHVsZXMvbmFub2lkL25vbi1zZWN1cmUvaW5kZXguanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3J1bnRpbWUuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXIuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZC5qcyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvc3lzdGVtLmpzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jb250ZXh0bWVudS5qcyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3MuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RyYWcuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3NjcmVlbnMuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dpbmRvdy5qcyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvd21sLmpzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9ldmVudHMuanMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50X3R5cGVzLmpzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9kaWFsb2dzLmpzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxscy5qcyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvY29tcGlsZWQvbWFpbi5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBMb2dzIGEgbWVzc2FnZSB0byB0aGUgY29uc29sZSB3aXRoIGN1c3RvbSBmb3JtYXR0aW5nLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVidWdMb2cobWVzc2FnZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAnJWMgd2FpbHMzICVjICcgKyBtZXNzYWdlICsgJyAnLFxuICAgICAgICAnYmFja2dyb3VuZDogI2FhMDAwMDsgY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDNweCAwcHggMHB4IDNweDsgcGFkZGluZzogMXB4OyBmb250LXNpemU6IDAuN3JlbScsXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjMDA5OTAwOyBjb2xvcjogI2ZmZjsgYm9yZGVyLXJhZGl1czogMHB4IDNweCAzcHggMHB4OyBwYWRkaW5nOiAxcHg7IGZvbnQtc2l6ZTogMC43cmVtJ1xuICAgICk7XG59IiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZVwiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQXBwbGljYXRpb24sICcnKTtcblxuY29uc3QgSGlkZU1ldGhvZCA9IDA7XG5jb25zdCBTaG93TWV0aG9kID0gMTtcbmNvbnN0IFF1aXRNZXRob2QgPSAyO1xuXG4vKipcbiAqIEhpZGVzIGEgY2VydGFpbiBtZXRob2QgYnkgY2FsbGluZyB0aGUgSGlkZU1ldGhvZCBmdW5jdGlvbi5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XG4gICAgcmV0dXJuIGNhbGwoSGlkZU1ldGhvZCk7XG59XG5cbi8qKlxuICogQ2FsbHMgdGhlIFNob3dNZXRob2QgYW5kIHJldHVybnMgdGhlIHJlc3VsdC5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpIHtcbiAgICByZXR1cm4gY2FsbChTaG93TWV0aG9kKTtcbn1cblxuLyoqXG4gKiBDYWxscyB0aGUgUXVpdE1ldGhvZCB0byB0ZXJtaW5hdGUgdGhlIHByb2dyYW0uXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFF1aXQoKSB7XG4gICAgcmV0dXJuIGNhbGwoUXVpdE1ldGhvZCk7XG59XG4iLCAibGV0IHVybEFscGhhYmV0ID1cbiAgJ3VzZWFuZG9tLTI2VDE5ODM0MFBYNzVweEpBQ0tWRVJZTUlOREJVU0hXT0xGX0dRWmJmZ2hqa2xxdnd5enJpY3QnXG5leHBvcnQgbGV0IGN1c3RvbUFscGhhYmV0ID0gKGFscGhhYmV0LCBkZWZhdWx0U2l6ZSA9IDIxKSA9PiB7XG4gIHJldHVybiAoc2l6ZSA9IGRlZmF1bHRTaXplKSA9PiB7XG4gICAgbGV0IGlkID0gJydcbiAgICBsZXQgaSA9IHNpemVcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICBpZCArPSBhbHBoYWJldFsoTWF0aC5yYW5kb20oKSAqIGFscGhhYmV0Lmxlbmd0aCkgfCAwXVxuICAgIH1cbiAgICByZXR1cm4gaWRcbiAgfVxufVxuZXhwb3J0IGxldCBuYW5vaWQgPSAoc2l6ZSA9IDIxKSA9PiB7XG4gIGxldCBpZCA9ICcnXG4gIGxldCBpID0gc2l6ZVxuICB3aGlsZSAoaS0tKSB7XG4gICAgaWQgKz0gdXJsQWxwaGFiZXRbKE1hdGgucmFuZG9tKCkgKiA2NCkgfCAwXVxuICB9XG4gIHJldHVybiBpZFxufVxuIiwgIi8qXG4gXyAgICAgX18gICAgIF8gX19cbnwgfCAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQgeyBuYW5vaWQgfSBmcm9tICduYW5vaWQvbm9uLXNlY3VyZSc7XG5cbmNvbnN0IHJ1bnRpbWVVUkwgPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luICsgXCIvd2FpbHMvcnVudGltZVwiO1xuXG4vLyBPYmplY3QgTmFtZXNcbmV4cG9ydCBjb25zdCBvYmplY3ROYW1lcyA9IHtcbiAgICBDYWxsOiAwLFxuICAgIENsaXBib2FyZDogMSxcbiAgICBBcHBsaWNhdGlvbjogMixcbiAgICBFdmVudHM6IDMsXG4gICAgQ29udGV4dE1lbnU6IDQsXG4gICAgRGlhbG9nOiA1LFxuICAgIFdpbmRvdzogNixcbiAgICBTY3JlZW5zOiA3LFxuICAgIFN5c3RlbTogOCxcbiAgICBCcm93c2VyOiA5LFxuICAgIENhbmNlbENhbGw6IDEwLFxufVxuZXhwb3J0IGxldCBjbGllbnRJZCA9IG5hbm9pZCgpO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBydW50aW1lIGNhbGxlciBmdW5jdGlvbiB0aGF0IGludm9rZXMgYSBzcGVjaWZpZWQgbWV0aG9kIG9uIGEgZ2l2ZW4gb2JqZWN0IHdpdGhpbiBhIHNwZWNpZmllZCB3aW5kb3cgY29udGV4dC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IC0gVGhlIG9iamVjdCBvbiB3aGljaCB0aGUgbWV0aG9kIGlzIHRvIGJlIGludm9rZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgY29udGV4dCBpbiB3aGljaCB0aGUgbWV0aG9kIHNob3VsZCBiZSBjYWxsZWQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IEEgcnVudGltZSBjYWxsZXIgZnVuY3Rpb24gdGhhdCB0YWtlcyB0aGUgbWV0aG9kIG5hbWUgYW5kIG9wdGlvbmFsbHkgYXJndW1lbnRzIGFuZCBpbnZva2VzIHRoZSBtZXRob2Qgd2l0aGluIHRoZSBzcGVjaWZpZWQgd2luZG93IGNvbnRleHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdCwgd2luZG93TmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAobWV0aG9kLCBhcmdzPW51bGwpIHtcbiAgICAgICAgcmV0dXJuIHJ1bnRpbWVDYWxsKG9iamVjdCArIFwiLlwiICsgbWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKTtcbiAgICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcnVudGltZSBjYWxsZXIgd2l0aCBzcGVjaWZpZWQgSUQuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3QgdG8gaW52b2tlIHRoZSBtZXRob2Qgb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cuXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gLSBUaGUgbmV3IHJ1bnRpbWUgY2FsbGVyIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3QsIHdpbmRvd05hbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG1ldGhvZCwgYXJncz1udWxsKSB7XG4gICAgICAgIHJldHVybiBydW50aW1lQ2FsbFdpdGhJRChvYmplY3QsIG1ldGhvZCwgd2luZG93TmFtZSwgYXJncyk7XG4gICAgfTtcbn1cblxuXG5mdW5jdGlvbiBydW50aW1lQ2FsbChtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcbiAgICBpZiggbWV0aG9kICkge1xuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcIm1ldGhvZFwiLCBtZXRob2QpO1xuICAgIH1cbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICB9O1xuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuICAgIGlmIChhcmdzKSB7XG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiYXJnc1wiLCBKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgfVxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGZldGNoKHVybCwgZmV0Y2hPcHRpb25zKVxuICAgICAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayBjb250ZW50IHR5cGVcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpICYmIHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpLmluZGV4T2YoXCJhcHBsaWNhdGlvbi9qc29uXCIpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKHJlc3BvbnNlLnN0YXR1c1RleHQpKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbihkYXRhID0+IHJlc29sdmUoZGF0YSkpXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHJ1bnRpbWVDYWxsV2l0aElEKG9iamVjdElELCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcbiAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcIm9iamVjdFwiLCBvYmplY3RJRCk7XG4gICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJtZXRob2RcIiwgbWV0aG9kKTtcbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICB9O1xuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuICAgIGlmIChhcmdzKSB7XG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiYXJnc1wiLCBKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgfVxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBmZXRjaCh1cmwsIGZldGNoT3B0aW9ucylcbiAgICAgICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgY29udGVudCB0eXBlXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKSAmJiByZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKS5pbmRleE9mKFwiYXBwbGljYXRpb24vanNvblwiKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcihyZXNwb25zZS5zdGF0dXNUZXh0KSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oZGF0YSA9PiByZXNvbHZlKGRhdGEpKVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgIH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkJyb3dzZXIsICcnKTtcbmNvbnN0IEJyb3dzZXJPcGVuVVJMID0gMDtcblxuLyoqXG4gKiBPcGVuIGEgYnJvd3NlciB3aW5kb3cgdG8gdGhlIGdpdmVuIFVSTFxuICogQHBhcmFtIHtzdHJpbmd9IHVybCAtIFRoZSBVUkwgdG8gb3BlblxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9wZW5VUkwodXJsKSB7XG4gICAgcmV0dXJuIGNhbGwoQnJvd3Nlck9wZW5VUkwsIHt1cmx9KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkNsaXBib2FyZCwgJycpO1xuY29uc3QgQ2xpcGJvYXJkU2V0VGV4dCA9IDA7XG5jb25zdCBDbGlwYm9hcmRUZXh0ID0gMTtcblxuLyoqXG4gKiBTZXRzIHRoZSB0ZXh0IHRvIHRoZSBDbGlwYm9hcmQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgdGV4dCB0byBiZSBzZXQgdG8gdGhlIENsaXBib2FyZC5cbiAqIEByZXR1cm4ge1Byb21pc2V9IC0gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIHN1Y2Nlc3NmdWwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRUZXh0KHRleHQpIHtcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRTZXRUZXh0LCB7dGV4dH0pO1xufVxuXG4vKipcbiAqIEdldCB0aGUgQ2xpcGJvYXJkIHRleHRcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHRleHQgZnJvbSB0aGUgQ2xpcGJvYXJkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gVGV4dCgpIHtcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRUZXh0KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5sZXQgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU3lzdGVtLCAnJyk7XG5jb25zdCBzeXN0ZW1Jc0RhcmtNb2RlID0gMDtcbmNvbnN0IGVudmlyb25tZW50ID0gMTtcblxuZXhwb3J0IGZ1bmN0aW9uIGludm9rZShtc2cpIHtcbiAgICBpZih3aW5kb3cuY2hyb21lKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuY2hyb21lLndlYnZpZXcucG9zdE1lc3NhZ2UobXNnKTtcbiAgICB9XG4gICAgcmV0dXJuIHdpbmRvdy53ZWJraXQubWVzc2FnZUhhbmRsZXJzLmV4dGVybmFsLnBvc3RNZXNzYWdlKG1zZyk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBSZXRyaWV2ZXMgdGhlIHN5c3RlbSBkYXJrIG1vZGUgc3RhdHVzLlxuICogQHJldHVybnMge1Byb21pc2U8Ym9vbGVhbj59IC0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBib29sZWFuIHZhbHVlIGluZGljYXRpbmcgaWYgdGhlIHN5c3RlbSBpcyBpbiBkYXJrIG1vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0RhcmtNb2RlKCkge1xuICAgIHJldHVybiBjYWxsKHN5c3RlbUlzRGFya01vZGUpO1xufVxuXG4vKipcbiAqIEZldGNoZXMgdGhlIGNhcGFiaWxpdGllcyBvZiB0aGUgYXBwbGljYXRpb24gZnJvbSB0aGUgc2VydmVyLlxuICpcbiAqIEBhc3luY1xuICogQGZ1bmN0aW9uIENhcGFiaWxpdGllc1xuICogQHJldHVybnMge1Byb21pc2U8T2JqZWN0Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGNhcGFiaWxpdGllcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhcGFiaWxpdGllcygpIHtcbiAgICBsZXQgcmVzcG9uc2UgPSBmZXRjaChcIi93YWlscy9jYXBhYmlsaXRpZXNcIik7XG4gICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbn1cblxuLyoqXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBFbnZpcm9ubWVudEluZm9cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBPUyAtIFRoZSBvcGVyYXRpbmcgc3lzdGVtIGluIHVzZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBBcmNoIC0gVGhlIGFyY2hpdGVjdHVyZSBvZiB0aGUgc3lzdGVtLlxuICovXG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBSZXRyaWV2ZXMgZW52aXJvbm1lbnQgZGV0YWlscy5cbiAqIEByZXR1cm5zIHtQcm9taXNlPEVudmlyb25tZW50SW5mbz59IC0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgT1MgYW5kIHN5c3RlbSBhcmNoaXRlY3R1cmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFbnZpcm9ubWVudCgpIHtcbiAgICByZXR1cm4gY2FsbChlbnZpcm9ubWVudCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cy5cbiAqXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBvcGVyYXRpbmcgc3lzdGVtIGlzIFdpbmRvd3MsIG90aGVyd2lzZSBmYWxzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzV2luZG93cygpIHtcbiAgICByZXR1cm4gd2luZG93Ll93YWlscy5lbnZpcm9ubWVudC5PUyA9PT0gXCJ3aW5kb3dzXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgTGludXguXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIExpbnV4LCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0xpbnV4KCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcImxpbnV4XCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGlzIGEgbWFjT1Mgb3BlcmF0aW5nIHN5c3RlbS5cbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgZW52aXJvbm1lbnQgaXMgbWFjT1MsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzTWFjKCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcImRhcndpblwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQU1ENjQoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuQXJjaCA9PT0gXCJhbWQ2NFwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBhcmNoaXRlY3R1cmUgaXMgQVJNLlxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBjdXJyZW50IGFyY2hpdGVjdHVyZSBpcyBBUk0sIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQVJNKCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZS5cbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBSZXR1cm5zIHRydWUgaWYgdGhlIGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZSwgb3RoZXJ3aXNlIHJldHVybnMgZmFsc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0FSTTY0KCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtNjRcIjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIElzRGVidWcoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuRGVidWcgPT09IHRydWU7XG59XG5cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5pbXBvcnQge0lzRGVidWd9IGZyb20gXCIuL3N5c3RlbVwiO1xuXG4vLyBzZXR1cFxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgY29udGV4dE1lbnVIYW5kbGVyKTtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ29udGV4dE1lbnUsICcnKTtcbmNvbnN0IENvbnRleHRNZW51T3BlbiA9IDA7XG5cbmZ1bmN0aW9uIG9wZW5Db250ZXh0TWVudShpZCwgeCwgeSwgZGF0YSkge1xuICAgIHZvaWQgY2FsbChDb250ZXh0TWVudU9wZW4sIHtpZCwgeCwgeSwgZGF0YX0pO1xufVxuXG5mdW5jdGlvbiBjb250ZXh0TWVudUhhbmRsZXIoZXZlbnQpIHtcbiAgICAvLyBDaGVjayBmb3IgY3VzdG9tIGNvbnRleHQgbWVudVxuICAgIGxldCBlbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgIGxldCBjdXN0b21Db250ZXh0TWVudSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoXCItLWN1c3RvbS1jb250ZXh0bWVudVwiKTtcbiAgICBjdXN0b21Db250ZXh0TWVudSA9IGN1c3RvbUNvbnRleHRNZW51ID8gY3VzdG9tQ29udGV4dE1lbnUudHJpbSgpIDogXCJcIjtcbiAgICBpZiAoY3VzdG9tQ29udGV4dE1lbnUpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgbGV0IGN1c3RvbUNvbnRleHRNZW51RGF0YSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoXCItLWN1c3RvbS1jb250ZXh0bWVudS1kYXRhXCIpO1xuICAgICAgICBvcGVuQ29udGV4dE1lbnUoY3VzdG9tQ29udGV4dE1lbnUsIGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFksIGN1c3RvbUNvbnRleHRNZW51RGF0YSk7XG4gICAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpO1xufVxuXG5cbi8qXG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IGF1dG87IChkZWZhdWx0KSB3aWxsIHNob3cgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51IGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlIE9SIHRleHQgaGFzIGJlZW4gc2VsZWN0ZWQgT1IgZWxlbWVudCBpcyBpbnB1dCBvciB0ZXh0YXJlYVxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBzaG93OyB3aWxsIGFsd2F5cyBzaG93IHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBoaWRlOyB3aWxsIGFsd2F5cyBoaWRlIHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuXG5UaGlzIHJ1bGUgaXMgaW5oZXJpdGVkIGxpa2Ugbm9ybWFsIENTUyBydWxlcywgc28gbmVzdGluZyB3b3JrcyBhcyBleHBlY3RlZFxuKi9cbmZ1bmN0aW9uIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpIHtcblxuICAgIC8vIERlYnVnIGJ1aWxkcyBhbHdheXMgc2hvdyB0aGUgbWVudVxuICAgIGlmIChJc0RlYnVnKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFByb2Nlc3MgZGVmYXVsdCBjb250ZXh0IG1lbnVcbiAgICBjb25zdCBlbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgIGNvbnN0IGNvbXB1dGVkU3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KTtcbiAgICBjb25zdCBkZWZhdWx0Q29udGV4dE1lbnVBY3Rpb24gPSBjb21wdXRlZFN0eWxlLmdldFByb3BlcnR5VmFsdWUoXCItLWRlZmF1bHQtY29udGV4dG1lbnVcIikudHJpbSgpO1xuICAgIHN3aXRjaCAoZGVmYXVsdENvbnRleHRNZW51QWN0aW9uKSB7XG4gICAgICAgIGNhc2UgXCJzaG93XCI6XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNhc2UgXCJoaWRlXCI6XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgY29udGVudEVkaXRhYmxlIGlzIHRydWVcbiAgICAgICAgICAgIGlmIChlbGVtZW50LmlzQ29udGVudEVkaXRhYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0ZXh0IGhhcyBiZWVuIHNlbGVjdGVkXG4gICAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICAgICAgICBjb25zdCBoYXNTZWxlY3Rpb24gPSAoc2VsZWN0aW9uLnRvU3RyaW5nKCkubGVuZ3RoID4gMClcbiAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGVjdGlvbi5yYW5nZUNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdChpKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVjdHMgPSByYW5nZS5nZXRDbGllbnRSZWN0cygpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHJlY3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0ID0gcmVjdHNbal07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludChyZWN0LmxlZnQsIHJlY3QudG9wKSA9PT0gZWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRhZ25hbWUgaXMgaW5wdXQgb3IgdGV4dGFyZWFcbiAgICAgICAgICAgIGlmIChlbGVtZW50LnRhZ05hbWUgPT09IFwiSU5QVVRcIiB8fCBlbGVtZW50LnRhZ05hbWUgPT09IFwiVEVYVEFSRUFcIikge1xuICAgICAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24gfHwgKCFlbGVtZW50LnJlYWRPbmx5ICYmICFlbGVtZW50LmRpc2FibGVkKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBoaWRlIGRlZmF1bHQgY29udGV4dCBtZW51XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIFJldHJpZXZlcyB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBzcGVjaWZpZWQga2V5IGZyb20gdGhlIGZsYWcgbWFwLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXlTdHJpbmcgLSBUaGUga2V5IHRvIHJldHJpZXZlIHRoZSB2YWx1ZSBmb3IuXG4gKiBAcmV0dXJuIHsqfSAtIFRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBrZXkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRGbGFnKGtleVN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmZsYWdzW2tleVN0cmluZ107XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gcmV0cmlldmUgZmxhZyAnXCIgKyBrZXlTdHJpbmcgKyBcIic6IFwiICsgZSk7XG4gICAgfVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7aW52b2tlLCBJc1dpbmRvd3N9IGZyb20gXCIuL3N5c3RlbVwiO1xuaW1wb3J0IHtHZXRGbGFnfSBmcm9tIFwiLi9mbGFnc1wiO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLnNldFJlc2l6YWJsZSA9IHNldFJlc2l6YWJsZTtcbndpbmRvdy5fd2FpbHMuZW5kRHJhZyA9IGVuZERyYWc7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgb25Nb3VzZURvd24pO1xud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG9uTW91c2VNb3ZlKTtcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25Nb3VzZVVwKTtcblxuXG5sZXQgc2hvdWxkRHJhZyA9IGZhbHNlO1xubGV0IHJlc2l6ZUVkZ2UgPSBudWxsO1xubGV0IHJlc2l6YWJsZSA9IGZhbHNlO1xubGV0IGRlZmF1bHRDdXJzb3IgPSBcImF1dG9cIjtcblxuZnVuY3Rpb24gZHJhZ1Rlc3QoZSkge1xuICAgIGxldCB2YWwgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlLnRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZShcIi0td2Via2l0LWFwcC1yZWdpb25cIik7XG4gICAgaWYgKCF2YWwgfHwgdmFsID09PSBcIlwiIHx8IHZhbC50cmltKCkgIT09IFwiZHJhZ1wiIHx8IGUuYnV0dG9ucyAhPT0gMSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBlLmRldGFpbCA9PT0gMTtcbn1cblxuZnVuY3Rpb24gc2V0UmVzaXphYmxlKHZhbHVlKSB7XG4gICAgcmVzaXphYmxlID0gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIGVuZERyYWcoKSB7XG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5jdXJzb3IgPSAnZGVmYXVsdCc7XG4gICAgc2hvdWxkRHJhZyA9IGZhbHNlO1xufVxuXG5mdW5jdGlvbiB0ZXN0UmVzaXplKCkge1xuICAgIGlmKCByZXNpemVFZGdlICkge1xuICAgICAgICBpbnZva2UoYHJlc2l6ZToke3Jlc2l6ZUVkZ2V9YCk7XG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gb25Nb3VzZURvd24oZSkge1xuICAgIGlmKElzV2luZG93cygpICYmIHRlc3RSZXNpemUoKSB8fCBkcmFnVGVzdChlKSkge1xuICAgICAgICBzaG91bGREcmFnID0gISFpc1ZhbGlkRHJhZyhlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzVmFsaWREcmFnKGUpIHtcbiAgICAvLyBJZ25vcmUgZHJhZyBvbiBzY3JvbGxiYXJzXG4gICAgcmV0dXJuICEoZS5vZmZzZXRYID4gZS50YXJnZXQuY2xpZW50V2lkdGggfHwgZS5vZmZzZXRZID4gZS50YXJnZXQuY2xpZW50SGVpZ2h0KTtcbn1cblxuZnVuY3Rpb24gb25Nb3VzZVVwKGUpIHtcbiAgICBsZXQgbW91c2VQcmVzc2VkID0gZS5idXR0b25zICE9PSB1bmRlZmluZWQgPyBlLmJ1dHRvbnMgOiBlLndoaWNoO1xuICAgIGlmIChtb3VzZVByZXNzZWQgPiAwKSB7XG4gICAgICAgIGVuZERyYWcoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldFJlc2l6ZShjdXJzb3IgPSBkZWZhdWx0Q3Vyc29yKSB7XG4gICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmN1cnNvciA9IGN1cnNvcjtcbiAgICByZXNpemVFZGdlID0gY3Vyc29yO1xufVxuXG5mdW5jdGlvbiBvbk1vdXNlTW92ZShlKSB7XG4gICAgc2hvdWxkRHJhZyA9IGNoZWNrRHJhZyhlKTtcbiAgICBpZiAoSXNXaW5kb3dzKCkgJiYgcmVzaXphYmxlKSB7XG4gICAgICAgIGhhbmRsZVJlc2l6ZShlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrRHJhZyhlKSB7XG4gICAgbGV0IG1vdXNlUHJlc3NlZCA9IGUuYnV0dG9ucyAhPT0gdW5kZWZpbmVkID8gZS5idXR0b25zIDogZS53aGljaDtcbiAgICBpZihzaG91bGREcmFnICYmIG1vdXNlUHJlc3NlZCA+IDApIHtcbiAgICAgICAgaW52b2tlKFwiZHJhZ1wiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gc2hvdWxkRHJhZztcbn1cblxuZnVuY3Rpb24gaGFuZGxlUmVzaXplKGUpIHtcbiAgICBsZXQgcmVzaXplSGFuZGxlSGVpZ2h0ID0gR2V0RmxhZyhcInN5c3RlbS5yZXNpemVIYW5kbGVIZWlnaHRcIikgfHwgNTtcbiAgICBsZXQgcmVzaXplSGFuZGxlV2lkdGggPSBHZXRGbGFnKFwic3lzdGVtLnJlc2l6ZUhhbmRsZVdpZHRoXCIpIHx8IDU7XG5cbiAgICAvLyBFeHRyYSBwaXhlbHMgZm9yIHRoZSBjb3JuZXIgYXJlYXNcbiAgICBsZXQgY29ybmVyRXh0cmEgPSBHZXRGbGFnKFwicmVzaXplQ29ybmVyRXh0cmFcIikgfHwgMTA7XG5cbiAgICBsZXQgcmlnaHRCb3JkZXIgPSB3aW5kb3cub3V0ZXJXaWR0aCAtIGUuY2xpZW50WCA8IHJlc2l6ZUhhbmRsZVdpZHRoO1xuICAgIGxldCBsZWZ0Qm9yZGVyID0gZS5jbGllbnRYIDwgcmVzaXplSGFuZGxlV2lkdGg7XG4gICAgbGV0IHRvcEJvcmRlciA9IGUuY2xpZW50WSA8IHJlc2l6ZUhhbmRsZUhlaWdodDtcbiAgICBsZXQgYm90dG9tQm9yZGVyID0gd2luZG93Lm91dGVySGVpZ2h0IC0gZS5jbGllbnRZIDwgcmVzaXplSGFuZGxlSGVpZ2h0O1xuXG4gICAgLy8gQWRqdXN0IGZvciBjb3JuZXJzXG4gICAgbGV0IHJpZ2h0Q29ybmVyID0gd2luZG93Lm91dGVyV2lkdGggLSBlLmNsaWVudFggPCAocmVzaXplSGFuZGxlV2lkdGggKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IGxlZnRDb3JuZXIgPSBlLmNsaWVudFggPCAocmVzaXplSGFuZGxlV2lkdGggKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IHRvcENvcm5lciA9IGUuY2xpZW50WSA8IChyZXNpemVIYW5kbGVIZWlnaHQgKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IGJvdHRvbUNvcm5lciA9IHdpbmRvdy5vdXRlckhlaWdodCAtIGUuY2xpZW50WSA8IChyZXNpemVIYW5kbGVIZWlnaHQgKyBjb3JuZXJFeHRyYSk7XG5cbiAgICAvLyBJZiB3ZSBhcmVuJ3Qgb24gYW4gZWRnZSwgYnV0IHdlcmUsIHJlc2V0IHRoZSBjdXJzb3IgdG8gZGVmYXVsdFxuICAgIGlmICghbGVmdEJvcmRlciAmJiAhcmlnaHRCb3JkZXIgJiYgIXRvcEJvcmRlciAmJiAhYm90dG9tQm9yZGVyICYmIHJlc2l6ZUVkZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzZXRSZXNpemUoKTtcbiAgICB9XG4gICAgLy8gQWRqdXN0ZWQgZm9yIGNvcm5lciBhcmVhc1xuICAgIGVsc2UgaWYgKHJpZ2h0Q29ybmVyICYmIGJvdHRvbUNvcm5lcikgc2V0UmVzaXplKFwic2UtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRDb3JuZXIgJiYgYm90dG9tQ29ybmVyKSBzZXRSZXNpemUoXCJzdy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAobGVmdENvcm5lciAmJiB0b3BDb3JuZXIpIHNldFJlc2l6ZShcIm53LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BDb3JuZXIgJiYgcmlnaHRDb3JuZXIpIHNldFJlc2l6ZShcIm5lLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Qm9yZGVyKSBzZXRSZXNpemUoXCJ3LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BCb3JkZXIpIHNldFJlc2l6ZShcIm4tcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwicy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAocmlnaHRCb3JkZXIpIHNldFJlc2l6ZShcImUtcmVzaXplXCIpO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUG9zaXRpb25cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIFggY29vcmRpbmF0ZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBZIC0gVGhlIFkgY29vcmRpbmF0ZS5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNpemVcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIHdpZHRoLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFkgLSBUaGUgaGVpZ2h0LlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBSZWN0XG4gKiBAcHJvcGVydHkge251bWJlcn0gWCAtIFRoZSBYIGNvb3JkaW5hdGUgb2YgdGhlIHRvcC1sZWZ0IGNvcm5lci5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBZIC0gVGhlIFkgY29vcmRpbmF0ZSBvZiB0aGUgdG9wLWxlZnQgY29ybmVyLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSByZWN0YW5nbGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gSGVpZ2h0IC0gVGhlIGhlaWdodCBvZiB0aGUgcmVjdGFuZ2xlLlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7KCdaZXJvJ3wnTmluZXR5J3wnT25lRWlnaHR5J3wnVHdvU2V2ZW50eScpfSBSb3RhdGlvblxuICogVGhlIHJvdGF0aW9uIG9mIHRoZSBzY3JlZW4uIENhbiBiZSBvbmUgb2YgJ1plcm8nLCAnTmluZXR5JywgJ09uZUVpZ2h0eScsICdUd29TZXZlbnR5Jy5cbiAqL1xuXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gU2NyZWVuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSWQgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHNjcmVlbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBOYW1lIC0gSHVtYW4gcmVhZGFibGUgbmFtZSBvZiB0aGUgc2NyZWVuLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFNjYWxlIC0gVGhlIHJlc29sdXRpb24gc2NhbGUgb2YgdGhlIHNjcmVlbi4gMSA9IHN0YW5kYXJkIHJlc29sdXRpb24sIDIgPSBoaWdoIChSZXRpbmEpLCBldGMuXG4gKiBAcHJvcGVydHkge1Bvc2l0aW9ufSBQb3NpdGlvbiAtIENvbnRhaW5zIHRoZSBYIGFuZCBZIGNvb3JkaW5hdGVzIG9mIHRoZSBzY3JlZW4ncyBwb3NpdGlvbi5cbiAqIEBwcm9wZXJ0eSB7U2l6ZX0gU2l6ZSAtIENvbnRhaW5zIHRoZSB3aWR0aCBhbmQgaGVpZ2h0IG9mIHRoZSBzY3JlZW4uXG4gKiBAcHJvcGVydHkge1JlY3R9IEJvdW5kcyAtIENvbnRhaW5zIHRoZSBib3VuZHMgb2YgdGhlIHNjcmVlbiBpbiB0ZXJtcyBvZiBYLCBZLCBXaWR0aCwgYW5kIEhlaWdodC5cbiAqIEBwcm9wZXJ0eSB7UmVjdH0gV29ya0FyZWEgLSBDb250YWlucyB0aGUgYXJlYSBvZiB0aGUgc2NyZWVuIHRoYXQgaXMgYWN0dWFsbHkgdXNhYmxlIChleGNsdWRpbmcgdGFza2JhciBhbmQgb3RoZXIgc3lzdGVtIFVJKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gSXNQcmltYXJ5IC0gVHJ1ZSBpZiB0aGlzIGlzIHRoZSBwcmltYXJ5IG1vbml0b3Igc2VsZWN0ZWQgYnkgdGhlIHVzZXIgaW4gdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gKiBAcHJvcGVydHkge1JvdGF0aW9ufSBSb3RhdGlvbiAtIFRoZSByb3RhdGlvbiBvZiB0aGUgc2NyZWVuLlxuICovXG5cblxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU2NyZWVucywgJycpO1xuXG5jb25zdCBnZXRBbGwgPSAwO1xuY29uc3QgZ2V0UHJpbWFyeSA9IDE7XG5jb25zdCBnZXRDdXJyZW50ID0gMjtcblxuLyoqXG4gKiBHZXRzIGFsbCBzY3JlZW5zLlxuICogQHJldHVybnMge1Byb21pc2U8U2NyZWVuW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiBTY3JlZW4gb2JqZWN0cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldEFsbCgpIHtcbiAgICByZXR1cm4gY2FsbChnZXRBbGwpO1xufVxuLyoqXG4gKiBHZXRzIHRoZSBwcmltYXJ5IHNjcmVlbi5cbiAqIEByZXR1cm5zIHtQcm9taXNlPFNjcmVlbj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBwcmltYXJ5IHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldFByaW1hcnkoKSB7XG4gICAgcmV0dXJuIGNhbGwoZ2V0UHJpbWFyeSk7XG59XG4vKipcbiAqIEdldHMgdGhlIGN1cnJlbnQgYWN0aXZlIHNjcmVlbi5cbiAqXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxTY3JlZW4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjdXJyZW50IGFjdGl2ZSBzY3JlZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRDdXJyZW50KCkge1xuICAgIHJldHVybiBjYWxsKGdldEN1cnJlbnQpO1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vLyBJbXBvcnQgc2NyZWVuIGpzZG9jIGRlZmluaXRpb24gZnJvbSAuL3NjcmVlbnMuanNcbi8qKlxuICogQHR5cGVkZWYge2ltcG9ydChcIi4vc2NyZWVuc1wiKS5TY3JlZW59IFNjcmVlblxuICovXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcblxuY29uc3QgY2VudGVyID0gMDtcbmNvbnN0IHNldFRpdGxlID0gMTtcbmNvbnN0IGZ1bGxzY3JlZW4gPSAyO1xuY29uc3QgdW5GdWxsc2NyZWVuID0gMztcbmNvbnN0IHNldFNpemUgPSA0O1xuY29uc3Qgc2l6ZSA9IDU7XG5jb25zdCBzZXRNYXhTaXplID0gNjtcbmNvbnN0IHNldE1pblNpemUgPSA3O1xuY29uc3Qgc2V0QWx3YXlzT25Ub3AgPSA4O1xuY29uc3Qgc2V0UmVsYXRpdmVQb3NpdGlvbiA9IDk7XG5jb25zdCByZWxhdGl2ZVBvc2l0aW9uID0gMTA7XG5jb25zdCBzY3JlZW4gPSAxMTtcbmNvbnN0IGhpZGUgPSAxMjtcbmNvbnN0IG1heGltaXNlID0gMTM7XG5jb25zdCB1bk1heGltaXNlID0gMTQ7XG5jb25zdCB0b2dnbGVNYXhpbWlzZSA9IDE1O1xuY29uc3QgbWluaW1pc2UgPSAxNjtcbmNvbnN0IHVuTWluaW1pc2UgPSAxNztcbmNvbnN0IHJlc3RvcmUgPSAxODtcbmNvbnN0IHNob3cgPSAxOTtcbmNvbnN0IGNsb3NlID0gMjA7XG5jb25zdCBzZXRCYWNrZ3JvdW5kQ29sb3VyID0gMjE7XG5jb25zdCBzZXRSZXNpemFibGUgPSAyMjtcbmNvbnN0IHdpZHRoID0gMjM7XG5jb25zdCBoZWlnaHQgPSAyNDtcbmNvbnN0IHpvb21JbiA9IDI1O1xuY29uc3Qgem9vbU91dCA9IDI2O1xuY29uc3Qgem9vbVJlc2V0ID0gMjc7XG5jb25zdCBnZXRab29tTGV2ZWwgPSAyODtcbmNvbnN0IHNldFpvb21MZXZlbCA9IDI5O1xuXG5jb25zdCB0aGlzV2luZG93ID0gR2V0KCcnKTtcblxuZnVuY3Rpb24gY3JlYXRlV2luZG93KGNhbGwpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBHZXQ6ICh3aW5kb3dOYW1lKSA9PiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKSxcbiAgICAgICAgQ2VudGVyOiAoKSA9PiBjYWxsKGNlbnRlciksXG4gICAgICAgIFNldFRpdGxlOiAodGl0bGUpID0+IGNhbGwoc2V0VGl0bGUsIHt0aXRsZX0pLFxuICAgICAgICBGdWxsc2NyZWVuOiAoKSA9PiBjYWxsKGZ1bGxzY3JlZW4pLFxuICAgICAgICBVbkZ1bGxzY3JlZW46ICgpID0+IGNhbGwodW5GdWxsc2NyZWVuKSxcbiAgICAgICAgU2V0U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2l6ZTogKCkgPT4gY2FsbChzaXplKSxcbiAgICAgICAgU2V0TWF4U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWF4U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2V0TWluU2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWluU2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2V0QWx3YXlzT25Ub3A6IChvblRvcCkgPT4gY2FsbChzZXRBbHdheXNPblRvcCwge2Fsd2F5c09uVG9wOiBvblRvcH0pLFxuICAgICAgICBTZXRSZWxhdGl2ZVBvc2l0aW9uOiAoeCwgeSkgPT4gY2FsbChzZXRSZWxhdGl2ZVBvc2l0aW9uLCB7eCwgeX0pLFxuICAgICAgICBSZWxhdGl2ZVBvc2l0aW9uOiAoKSA9PiBjYWxsKHJlbGF0aXZlUG9zaXRpb24pLFxuICAgICAgICBTY3JlZW46ICgpID0+IGNhbGwoc2NyZWVuKSxcbiAgICAgICAgSGlkZTogKCkgPT4gY2FsbChoaWRlKSxcbiAgICAgICAgTWF4aW1pc2U6ICgpID0+IGNhbGwobWF4aW1pc2UpLFxuICAgICAgICBVbk1heGltaXNlOiAoKSA9PiBjYWxsKHVuTWF4aW1pc2UpLFxuICAgICAgICBUb2dnbGVNYXhpbWlzZTogKCkgPT4gY2FsbCh0b2dnbGVNYXhpbWlzZSksXG4gICAgICAgIE1pbmltaXNlOiAoKSA9PiBjYWxsKG1pbmltaXNlKSxcbiAgICAgICAgVW5NaW5pbWlzZTogKCkgPT4gY2FsbCh1bk1pbmltaXNlKSxcbiAgICAgICAgUmVzdG9yZTogKCkgPT4gY2FsbChyZXN0b3JlKSxcbiAgICAgICAgU2hvdzogKCkgPT4gY2FsbChzaG93KSxcbiAgICAgICAgQ2xvc2U6ICgpID0+IGNhbGwoY2xvc2UpLFxuICAgICAgICBTZXRCYWNrZ3JvdW5kQ29sb3VyOiAociwgZywgYiwgYSkgPT4gY2FsbChzZXRCYWNrZ3JvdW5kQ29sb3VyLCB7ciwgZywgYiwgYX0pLFxuICAgICAgICBTZXRSZXNpemFibGU6IChyZXNpemFibGUpID0+IGNhbGwoc2V0UmVzaXphYmxlLCB7cmVzaXphYmxlfSksXG4gICAgICAgIFdpZHRoOiAoKSA9PiBjYWxsKHdpZHRoKSxcbiAgICAgICAgSGVpZ2h0OiAoKSA9PiBjYWxsKGhlaWdodCksXG4gICAgICAgIFpvb21JbjogKCkgPT4gY2FsbCh6b29tSW4pLFxuICAgICAgICBab29tT3V0OiAoKSA9PiBjYWxsKHpvb21PdXQpLFxuICAgICAgICBab29tUmVzZXQ6ICgpID0+IGNhbGwoem9vbVJlc2V0KSxcbiAgICAgICAgR2V0Wm9vbUxldmVsOiAoKSA9PiBjYWxsKGdldFpvb21MZXZlbCksXG4gICAgICAgIFNldFpvb21MZXZlbDogKHpvb21MZXZlbCkgPT4gY2FsbChzZXRab29tTGV2ZWwsIHt6b29tTGV2ZWx9KSxcbiAgICB9O1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNwZWNpZmllZCB3aW5kb3cuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHdpbmRvd05hbWUgLSBUaGUgbmFtZSBvZiB0aGUgd2luZG93IHRvIGdldC5cbiAqIEByZXR1cm4ge09iamVjdH0gLSBUaGUgc3BlY2lmaWVkIHdpbmRvdyBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXQod2luZG93TmFtZSkge1xuICAgIHJldHVybiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKTtcbn1cblxuLyoqXG4gKiBDZW50ZXJzIHRoZSB3aW5kb3cgb24gdGhlIHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENlbnRlcigpIHtcbiAgICB0aGlzV2luZG93LkNlbnRlcigpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIHRpdGxlIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGUgLSBUaGUgdGl0bGUgdG8gc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0VGl0bGUodGl0bGUpIHtcbiAgICB0aGlzV2luZG93LlNldFRpdGxlKHRpdGxlKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSB3aW5kb3cgdG8gZnVsbHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEZ1bGxzY3JlZW4oKSB7XG4gICAgdGhpc1dpbmRvdy5GdWxsc2NyZWVuKCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgc2l6ZSBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdGhpc1dpbmRvdy5TZXRTaXplKHdpZHRoLCBoZWlnaHQpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNpemUoKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2l6ZSgpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIG1heGltdW0gd2lkdGggb2YgdGhlIHdpbmRvdy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgLSBUaGUgbWF4aW11bSBoZWlnaHQgb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldE1heFNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXNXaW5kb3cuU2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aCAtIFRoZSBtaW5pbXVtIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIG1pbmltdW0gaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzV2luZG93LlNldE1pblNpemUod2lkdGgsIGhlaWdodCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgd2luZG93IHRvIGFsd2F5cyBiZSBvbiB0b3AuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IG9uVG9wIC0gV2hldGhlciB0aGUgd2luZG93IHNob3VsZCBhbHdheXMgYmUgb24gdG9wLlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0QWx3YXlzT25Ub3Aob25Ub3ApIHtcbiAgICB0aGlzV2luZG93LlNldEFsd2F5c09uVG9wKG9uVG9wKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSByZWxhdGl2ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHggLSBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSB3aW5kb3cncyBwb3NpdGlvbi5cbiAqIEBwYXJhbSB7bnVtYmVyfSB5IC0gVGhlIHktY29vcmRpbmF0ZSBvZiB0aGUgd2luZG93J3MgcG9zaXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRSZWxhdGl2ZVBvc2l0aW9uKHgsIHkpIHtcbiAgICB0aGlzV2luZG93LlNldFJlbGF0aXZlUG9zaXRpb24oeCwgeSk7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFJlbGF0aXZlUG9zaXRpb24oKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuUmVsYXRpdmVQb3NpdGlvbigpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNjcmVlbiB0aGF0IHRoZSB3aW5kb3cgaXMgb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTY3JlZW4oKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2NyZWVuKCk7XG59XG5cbi8qKlxuICogSGlkZXMgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XG4gICAgdGhpc1dpbmRvdy5IaWRlKCk7XG59XG5cbi8qKlxuICogTWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBNYXhpbWlzZSgpIHtcbiAgICB0aGlzV2luZG93Lk1heGltaXNlKCk7XG59XG5cbi8qKlxuICogVW4tbWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBVbk1heGltaXNlKCkge1xuICAgIHRoaXNXaW5kb3cuVW5NYXhpbWlzZSgpO1xufVxuXG4vKipcbiAqIFRvZ2dsZXMgdGhlIG1heGltaXNhdGlvbiBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gVG9nZ2xlTWF4aW1pc2UoKSB7XG4gICAgdGhpc1dpbmRvdy5Ub2dnbGVNYXhpbWlzZSgpO1xufVxuXG4vKipcbiAqIE1pbmltaXNlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gTWluaW1pc2UoKSB7XG4gICAgdGhpc1dpbmRvdy5NaW5pbWlzZSgpO1xufVxuXG4vKipcbiAqIFVuLW1pbmltaXNlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gVW5NaW5pbWlzZSgpIHtcbiAgICB0aGlzV2luZG93LlVuTWluaW1pc2UoKTtcbn1cblxuLyoqXG4gKiBSZXN0b3JlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVzdG9yZSgpIHtcbiAgICB0aGlzV2luZG93LlJlc3RvcmUoKTtcbn1cblxuLyoqXG4gKiBTaG93cyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpIHtcbiAgICB0aGlzV2luZG93LlNob3coKTtcbn1cblxuLyoqXG4gKiBDbG9zZXMgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENsb3NlKCkge1xuICAgIHRoaXNXaW5kb3cuQ2xvc2UoKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBiYWNrZ3JvdW5kIGNvbG91ciBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHIgLSBUaGUgcmVkIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxuICogQHBhcmFtIHtudW1iZXJ9IGcgLSBUaGUgZ3JlZW4gY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXG4gKiBAcGFyYW0ge251bWJlcn0gYiAtIFRoZSBibHVlIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxuICogQHBhcmFtIHtudW1iZXJ9IGEgLSBUaGUgYWxwaGEgY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRCYWNrZ3JvdW5kQ29sb3VyKHIsIGcsIGIsIGEpIHtcbiAgICB0aGlzV2luZG93LlNldEJhY2tncm91bmRDb2xvdXIociwgZywgYiwgYSk7XG59XG5cbi8qKlxuICogU2V0cyB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgcmVzaXphYmxlLlxuICogQHBhcmFtIHtib29sZWFufSByZXNpemFibGUgLSBXaGV0aGVyIHRoZSB3aW5kb3cgc2hvdWxkIGJlIHJlc2l6YWJsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldFJlc2l6YWJsZShyZXNpemFibGUpIHtcbiAgICB0aGlzV2luZG93LlNldFJlc2l6YWJsZShyZXNpemFibGUpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaWR0aCgpIHtcbiAgICByZXR1cm4gdGhpc1dpbmRvdy5XaWR0aCgpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gSGVpZ2h0KCkge1xuICAgIHJldHVybiB0aGlzV2luZG93LkhlaWdodCgpO1xufVxuXG4vKipcbiAqIFpvb21zIGluIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBab29tSW4oKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tSW4oKTtcbn1cblxuLyoqXG4gKiBab29tcyBvdXQgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFpvb21PdXQoKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tT3V0KCk7XG59XG5cbi8qKlxuICogUmVzZXRzIHRoZSB6b29tIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBab29tUmVzZXQoKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tUmVzZXQoKTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRab29tTGV2ZWwoKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuR2V0Wm9vbUxldmVsKCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHpvb21MZXZlbCAtIFRoZSB6b29tIGxldmVsIHRvIHNldC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldFpvb21MZXZlbCh6b29tTGV2ZWwpIHtcbiAgICB0aGlzV2luZG93LlNldFpvb21MZXZlbCh6b29tTGV2ZWwpO1xufVxuIiwgIlxuaW1wb3J0IHtFbWl0LCBXYWlsc0V2ZW50fSBmcm9tIFwiLi9ldmVudHNcIjtcbmltcG9ydCB7UXVlc3Rpb259IGZyb20gXCIuL2RpYWxvZ3NcIjtcbmltcG9ydCB7R2V0fSBmcm9tIFwiLi93aW5kb3dcIjtcbmltcG9ydCB7T3BlblVSTH0gZnJvbSBcIi4vYnJvd3NlclwiO1xuXG4vKipcbiAqIFNlbmRzIGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIG9wdGlvbmFsIGRhdGEuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBzZW5kLlxuICogQHBhcmFtIHthbnl9IFtkYXRhPW51bGxdIC0gT3B0aW9uYWwgZGF0YSB0byBzZW5kIGFsb25nIHdpdGggdGhlIGV2ZW50LlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHNlbmRFdmVudChldmVudE5hbWUsIGRhdGE9bnVsbCkge1xuICAgIGxldCBldmVudCA9IG5ldyBXYWlsc0V2ZW50KGV2ZW50TmFtZSwgZGF0YSk7XG4gICAgRW1pdChldmVudCk7XG59XG5cbi8qKlxuICogQWRkcyBldmVudCBsaXN0ZW5lcnMgdG8gZWxlbWVudHMgd2l0aCBgd21sLWV2ZW50YCBhdHRyaWJ1dGUuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gYWRkV01MRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLWV2ZW50XScpO1xuICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZXZlbnRUeXBlID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1ldmVudCcpO1xuICAgICAgICBjb25zdCBjb25maXJtID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1jb25maXJtJyk7XG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XG5cbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIERldGFjaGVkOiBmYWxzZSwgQnV0dG9uczpbe0xhYmVsOlwiWWVzXCJ9LHtMYWJlbDpcIk5vXCIsIElzRGVmYXVsdDp0cnVlfV19KS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPT0gXCJOb1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kRXZlbnQoZXZlbnRUeXBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbmRFdmVudChldmVudFR5cGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFJlbW92ZSBleGlzdGluZyBsaXN0ZW5lcnNcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcblxuICAgICAgICAvLyBBZGQgbmV3IGxpc3RlbmVyXG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XG4gICAgfSk7XG59XG5cblxuLyoqXG4gKiBDYWxscyBhIG1ldGhvZCBvbiBhIHNwZWNpZmllZCB3aW5kb3cuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgdG8gY2FsbCB0aGUgbWV0aG9kIG9uLlxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZCAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqL1xuZnVuY3Rpb24gY2FsbFdpbmRvd01ldGhvZCh3aW5kb3dOYW1lLCBtZXRob2QpIHtcbiAgICBsZXQgdGFyZ2V0V2luZG93ID0gR2V0KHdpbmRvd05hbWUpO1xuICAgIGxldCBtZXRob2RNYXAgPSBXaW5kb3dNZXRob2RzKHRhcmdldFdpbmRvdyk7XG4gICAgaWYgKCFtZXRob2RNYXAuaGFzKG1ldGhvZCkpIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJXaW5kb3cgbWV0aG9kIFwiICsgbWV0aG9kICsgXCIgbm90IGZvdW5kXCIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBtZXRob2RNYXAuZ2V0KG1ldGhvZCkoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBjYWxsaW5nIHdpbmRvdyBtZXRob2QgJ1wiICsgbWV0aG9kICsgXCInOiBcIiArIGUpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBZGRzIHdpbmRvdyBsaXN0ZW5lcnMgZm9yIGVsZW1lbnRzIHdpdGggdGhlICd3bWwtd2luZG93JyBhdHRyaWJ1dGUuXG4gKiBSZW1vdmVzIGFueSBleGlzdGluZyBsaXN0ZW5lcnMgYmVmb3JlIGFkZGluZyBuZXcgb25lcy5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5mdW5jdGlvbiBhZGRXTUxXaW5kb3dMaXN0ZW5lcnMoKSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLXdpbmRvd10nKTtcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IHdpbmRvd01ldGhvZCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtd2luZG93Jyk7XG4gICAgICAgIGNvbnN0IGNvbmZpcm0gPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWNvbmZpcm0nKTtcbiAgICAgICAgY29uc3QgdHJpZ2dlciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdHJpZ2dlcicpIHx8ICdjbGljayc7XG4gICAgICAgIGNvbnN0IHRhcmdldFdpbmRvdyA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdGFyZ2V0LXdpbmRvdycpIHx8ICcnO1xuXG4gICAgICAgIGxldCBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjb25maXJtKSB7XG4gICAgICAgICAgICAgICAgUXVlc3Rpb24oe1RpdGxlOiBcIkNvbmZpcm1cIiwgTWVzc2FnZTpjb25maXJtLCBCdXR0b25zOlt7TGFiZWw6XCJZZXNcIn0se0xhYmVsOlwiTm9cIiwgSXNEZWZhdWx0OnRydWV9XX0pLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9PSBcIk5vXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxXaW5kb3dNZXRob2QodGFyZ2V0V2luZG93LCB3aW5kb3dNZXRob2QpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FsbFdpbmRvd01ldGhvZCh0YXJnZXRXaW5kb3csIHdpbmRvd01ldGhvZCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUmVtb3ZlIGV4aXN0aW5nIGxpc3RlbmVyc1xuICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xuXG4gICAgICAgIC8vIEFkZCBuZXcgbGlzdGVuZXJcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBBZGRzIGEgbGlzdGVuZXIgdG8gZWxlbWVudHMgd2l0aCB0aGUgJ3dtbC1vcGVudXJsJyBhdHRyaWJ1dGUuXG4gKiBXaGVuIHRoZSBzcGVjaWZpZWQgdHJpZ2dlciBldmVudCBpcyBmaXJlZCBvbiBhbnkgb2YgdGhlc2UgZWxlbWVudHMsXG4gKiB0aGUgbGlzdGVuZXIgd2lsbCBvcGVuIHRoZSBVUkwgc3BlY2lmaWVkIGJ5IHRoZSAnd21sLW9wZW51cmwnIGF0dHJpYnV0ZS5cbiAqIElmIGEgJ3dtbC1jb25maXJtJyBhdHRyaWJ1dGUgaXMgcHJvdmlkZWQsIGEgY29uZmlybWF0aW9uIGRpYWxvZyB3aWxsIGJlIGRpc3BsYXllZCxcbiAqIGFuZCB0aGUgVVJMIHdpbGwgb25seSBiZSBvcGVuZWQgaWYgdGhlIHVzZXIgY29uZmlybXMuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpIHtcbiAgICBjb25zdCBlbGVtZW50cyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ1t3bWwtb3BlbnVybF0nKTtcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IHVybCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtb3BlbnVybCcpO1xuICAgICAgICBjb25zdCBjb25maXJtID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1jb25maXJtJyk7XG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XG5cbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIEJ1dHRvbnM6W3tMYWJlbDpcIlllc1wifSx7TGFiZWw6XCJOb1wiLCBJc0RlZmF1bHQ6dHJ1ZX1dfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT09IFwiTm9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCBPcGVuVVJMKHVybCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2b2lkIE9wZW5VUkwodXJsKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZW1vdmUgZXhpc3RpbmcgbGlzdGVuZXJzXG4gICAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XG5cbiAgICAgICAgLy8gQWRkIG5ldyBsaXN0ZW5lclxuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIFJlbG9hZHMgdGhlIFdNTCBwYWdlIGJ5IGFkZGluZyBuZWNlc3NhcnkgZXZlbnQgbGlzdGVuZXJzIGFuZCBicm93c2VyIGxpc3RlbmVycy5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVsb2FkKCkge1xuICAgIGFkZFdNTEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgYWRkV01MV2luZG93TGlzdGVuZXJzKCk7XG4gICAgYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBtYXAgb2YgYWxsIG1ldGhvZHMgaW4gdGhlIGN1cnJlbnQgd2luZG93LlxuICogQHJldHVybnMge01hcH0gLSBBIG1hcCBvZiB3aW5kb3cgbWV0aG9kcy5cbiAqL1xuZnVuY3Rpb24gV2luZG93TWV0aG9kcyh0YXJnZXRXaW5kb3cpIHtcbiAgICAvLyBDcmVhdGUgYSBuZXcgbWFwIHRvIHN0b3JlIG1ldGhvZHNcbiAgICBsZXQgcmVzdWx0ID0gbmV3IE1hcCgpO1xuXG4gICAgLy8gSXRlcmF0ZSBvdmVyIGFsbCBwcm9wZXJ0aWVzIG9mIHRoZSB3aW5kb3cgb2JqZWN0XG4gICAgZm9yIChsZXQgbWV0aG9kIGluIHRhcmdldFdpbmRvdykge1xuICAgICAgICAvLyBDaGVjayBpZiB0aGUgcHJvcGVydHkgaXMgaW5kZWVkIGEgbWV0aG9kIChmdW5jdGlvbilcbiAgICAgICAgaWYodHlwZW9mIHRhcmdldFdpbmRvd1ttZXRob2RdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAvLyBBZGQgdGhlIG1ldGhvZCB0byB0aGUgbWFwXG4gICAgICAgICAgICByZXN1bHQuc2V0KG1ldGhvZCwgdGFyZ2V0V2luZG93W21ldGhvZF0pO1xuICAgICAgICB9XG5cbiAgICB9XG4gICAgLy8gUmV0dXJuIHRoZSBtYXAgb2Ygd2luZG93IG1ldGhvZHNcbiAgICByZXR1cm4gcmVzdWx0O1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtpbXBvcnQoXCIuL3R5cGVzXCIpLldhaWxzRXZlbnR9IFdhaWxzRXZlbnRcbiAqL1xuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuXG5pbXBvcnQge0V2ZW50VHlwZXN9IGZyb20gXCIuL2V2ZW50X3R5cGVzXCI7XG5leHBvcnQgY29uc3QgVHlwZXMgPSBFdmVudFR5cGVzO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLmRpc3BhdGNoV2FpbHNFdmVudCA9IGRpc3BhdGNoV2FpbHNFdmVudDtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuRXZlbnRzLCAnJyk7XG5jb25zdCBFbWl0TWV0aG9kID0gMDtcbmNvbnN0IGV2ZW50TGlzdGVuZXJzID0gbmV3IE1hcCgpO1xuXG5jbGFzcyBMaXN0ZW5lciB7XG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgICAgIHRoaXMuZXZlbnROYW1lID0gZXZlbnROYW1lO1xuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICAgICAgdGhpcy5DYWxsYmFjayA9IChkYXRhKSA9PiB7XG4gICAgICAgICAgICBjYWxsYmFjayhkYXRhKTtcbiAgICAgICAgICAgIGlmICh0aGlzLm1heENhbGxiYWNrcyA9PT0gLTEpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMubWF4Q2FsbGJhY2tzIC09IDE7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXhDYWxsYmFja3MgPT09IDA7XG4gICAgICAgIH07XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2FpbHNFdmVudCB7XG4gICAgY29uc3RydWN0b3IobmFtZSwgZGF0YSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cCgpIHtcbn1cblxuZnVuY3Rpb24gZGlzcGF0Y2hXYWlsc0V2ZW50KGV2ZW50KSB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudC5uYW1lKTtcbiAgICBpZiAobGlzdGVuZXJzKSB7XG4gICAgICAgIGxldCB0b1JlbW92ZSA9IGxpc3RlbmVycy5maWx0ZXIobGlzdGVuZXIgPT4ge1xuICAgICAgICAgICAgbGV0IHJlbW92ZSA9IGxpc3RlbmVyLkNhbGxiYWNrKGV2ZW50KTtcbiAgICAgICAgICAgIGlmIChyZW1vdmUpIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHRvUmVtb3ZlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVycy5maWx0ZXIobCA9PiAhdG9SZW1vdmUuaW5jbHVkZXMobCkpO1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5sZW5ndGggPT09IDApIGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudC5uYW1lKTtcbiAgICAgICAgICAgIGVsc2UgZXZlbnRMaXN0ZW5lcnMuc2V0KGV2ZW50Lm5hbWUsIGxpc3RlbmVycyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogUmVnaXN0ZXIgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgbXVsdGlwbGUgdGltZXMgZm9yIGEgc3BlY2lmaWMgZXZlbnQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZWdpc3RlciB0aGUgY2FsbGJhY2sgZm9yLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIHRyaWdnZXJlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3MgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdGhlIGNhbGxiYWNrIGNhbiBiZSBjYWxsZWQgZm9yIHRoZSBldmVudC4gT25jZSB0aGUgbWF4aW11bSBudW1iZXIgaXMgcmVhY2hlZCwgdGhlIGNhbGxiYWNrIHdpbGwgbm8gbG9uZ2VyIGJlIGNhbGxlZC5cbiAqXG4gQHJldHVybiB7ZnVuY3Rpb259IC0gQSBmdW5jdGlvbiB0aGF0LCB3aGVuIGNhbGxlZCwgd2lsbCB1bnJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmcm9tIHRoZSBldmVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudE5hbWUpIHx8IFtdO1xuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xuICAgIGxpc3RlbmVycy5wdXNoKHRoaXNMaXN0ZW5lcik7XG4gICAgZXZlbnRMaXN0ZW5lcnMuc2V0KGV2ZW50TmFtZSwgbGlzdGVuZXJzKTtcbiAgICByZXR1cm4gKCkgPT4gbGlzdGVuZXJPZmYodGhpc0xpc3RlbmVyKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuIHRoZSBzcGVjaWZpZWQgZXZlbnQgb2NjdXJzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFjayAtIFRoZSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZC4gSXQgdGFrZXMgbm8gcGFyYW1ldGVycy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuICovXG5leHBvcnQgZnVuY3Rpb24gT24oZXZlbnROYW1lLCBjYWxsYmFjaykgeyByZXR1cm4gT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAtMSk7IH1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmx5IG9uY2UgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudC5cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGV2ZW50IG9jY3Vycy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHsgcmV0dXJuIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgMSk7IH1cblxuLyoqXG4gKiBSZW1vdmVzIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIgZnJvbSB0aGUgZXZlbnQgbGlzdGVuZXJzIGNvbGxlY3Rpb24uXG4gKiBJZiBhbGwgbGlzdGVuZXJzIGZvciB0aGUgZXZlbnQgYXJlIHJlbW92ZWQsIHRoZSBldmVudCBrZXkgaXMgZGVsZXRlZCBmcm9tIHRoZSBjb2xsZWN0aW9uLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBsaXN0ZW5lciAtIFRoZSBsaXN0ZW5lciB0byBiZSByZW1vdmVkLlxuICovXG5mdW5jdGlvbiBsaXN0ZW5lck9mZihsaXN0ZW5lcikge1xuICAgIGNvbnN0IGV2ZW50TmFtZSA9IGxpc3RlbmVyLmV2ZW50TmFtZTtcbiAgICBsZXQgbGlzdGVuZXJzID0gZXZlbnRMaXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSkuZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuICAgIGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSBldmVudExpc3RlbmVycy5kZWxldGUoZXZlbnROYW1lKTtcbiAgICBlbHNlIGV2ZW50TGlzdGVuZXJzLnNldChldmVudE5hbWUsIGxpc3RlbmVycyk7XG59XG5cblxuLyoqXG4gKiBSZW1vdmVzIGV2ZW50IGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudCBuYW1lcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSBsaXN0ZW5lcnMgZm9yLlxuICogQHBhcmFtIHsuLi5zdHJpbmd9IGFkZGl0aW9uYWxFdmVudE5hbWVzIC0gQWRkaXRpb25hbCBldmVudCBuYW1lcyB0byByZW1vdmUgbGlzdGVuZXJzIGZvci5cbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9mZihldmVudE5hbWUsIC4uLmFkZGl0aW9uYWxFdmVudE5hbWVzKSB7XG4gICAgbGV0IGV2ZW50c1RvUmVtb3ZlID0gW2V2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXNdO1xuICAgIGV2ZW50c1RvUmVtb3ZlLmZvckVhY2goZXZlbnROYW1lID0+IGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudE5hbWUpKTtcbn1cbi8qKlxuICogUmVtb3ZlcyBhbGwgZXZlbnQgbGlzdGVuZXJzLlxuICpcbiAqIEBmdW5jdGlvbiBPZmZBbGxcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gT2ZmQWxsKCkgeyBldmVudExpc3RlbmVycy5jbGVhcigpOyB9XG5cbi8qKlxuICogRW1pdHMgYW4gZXZlbnQgdXNpbmcgdGhlIGdpdmVuIGV2ZW50IG5hbWUuXG4gKlxuICogQHBhcmFtIHtXYWlsc0V2ZW50fSBldmVudCAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBlbWl0LlxuICogQHJldHVybnMge2FueX0gLSBUaGUgcmVzdWx0IG9mIHRoZSBlbWl0dGVkIGV2ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gRW1pdChldmVudCkgeyByZXR1cm4gY2FsbChFbWl0TWV0aG9kLCBldmVudCk7IH1cbiIsICJcbmV4cG9ydCBjb25zdCBFdmVudFR5cGVzID0ge1xuXHRXaW5kb3dzOiB7XG5cdFx0U3lzdGVtVGhlbWVDaGFuZ2VkOiBcIndpbmRvd3M6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdFx0QVBNUG93ZXJTdGF0dXNDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclN0YXR1c0NoYW5nZVwiLFxuXHRcdEFQTVN1c3BlbmQ6IFwid2luZG93czpBUE1TdXNwZW5kXCIsXG5cdFx0QVBNUmVzdW1lQXV0b21hdGljOiBcIndpbmRvd3M6QVBNUmVzdW1lQXV0b21hdGljXCIsXG5cdFx0QVBNUmVzdW1lU3VzcGVuZDogXCJ3aW5kb3dzOkFQTVJlc3VtZVN1c3BlbmRcIixcblx0XHRBUE1Qb3dlclNldHRpbmdDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclNldHRpbmdDaGFuZ2VcIixcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwid2luZG93czpBcHBsaWNhdGlvblN0YXJ0ZWRcIixcblx0XHRXZWJWaWV3TmF2aWdhdGlvbkNvbXBsZXRlZDogXCJ3aW5kb3dzOldlYlZpZXdOYXZpZ2F0aW9uQ29tcGxldGVkXCIsXG5cdFx0V2luZG93SW5hY3RpdmU6IFwid2luZG93czpXaW5kb3dJbmFjdGl2ZVwiLFxuXHRcdFdpbmRvd0FjdGl2ZTogXCJ3aW5kb3dzOldpbmRvd0FjdGl2ZVwiLFxuXHRcdFdpbmRvd0NsaWNrQWN0aXZlOiBcIndpbmRvd3M6V2luZG93Q2xpY2tBY3RpdmVcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcIndpbmRvd3M6V2luZG93RnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1VuRnVsbHNjcmVlbjogXCJ3aW5kb3dzOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwid2luZG93czpXaW5kb3dSZXN0b3JlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwid2luZG93czpXaW5kb3dNaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWluaW1pc2U6IFwid2luZG93czpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2U6IFwid2luZG93czpXaW5kb3dDbG9zZVwiLFxuXHRcdFdpbmRvd1NldEZvY3VzOiBcIndpbmRvd3M6V2luZG93U2V0Rm9jdXNcIixcblx0XHRXaW5kb3dLaWxsRm9jdXM6IFwid2luZG93czpXaW5kb3dLaWxsRm9jdXNcIixcblx0XHRXaW5kb3dEcmFnRHJvcDogXCJ3aW5kb3dzOldpbmRvd0RyYWdEcm9wXCIsXG5cdFx0V2luZG93RHJhZ0VudGVyOiBcIndpbmRvd3M6V2luZG93RHJhZ0VudGVyXCIsXG5cdFx0V2luZG93RHJhZ0xlYXZlOiBcIndpbmRvd3M6V2luZG93RHJhZ0xlYXZlXCIsXG5cdFx0V2luZG93RHJhZ092ZXI6IFwid2luZG93czpXaW5kb3dEcmFnT3ZlclwiLFxuXHR9LFxuXHRNYWM6IHtcblx0XHRBcHBsaWNhdGlvbkRpZEJlY29tZUFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUVmZmVjdGl2ZUFwcGVhcmFuY2VcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUljb246IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlSWNvblwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU2NyZWVuUGFyYW1ldGVyc1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uXCIsXG5cdFx0QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmc6IFwibWFjOkFwcGxpY2F0aW9uRGlkRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25EaWRIaWRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZEhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFJlc2lnbkFjdGl2ZU5vdGlmaWNhdGlvbjogXCJtYWM6QXBwbGljYXRpb25EaWRSZXNpZ25BY3RpdmVOb3RpZmljYXRpb25cIixcblx0XHRBcHBsaWNhdGlvbkRpZFVuaGlkZTogXCJtYWM6QXBwbGljYXRpb25EaWRVbmhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25EaWRVcGRhdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxCZWNvbWVBY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbEJlY29tZUFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEZpbmlzaExhdW5jaGluZzogXCJtYWM6QXBwbGljYXRpb25XaWxsRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsSGlkZTogXCJtYWM6QXBwbGljYXRpb25XaWxsSGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFJlc2lnbkFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVGVybWluYXRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxVbmhpZGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFVuaGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsVXBkYXRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZTogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZSFcIixcblx0XHRBcHBsaWNhdGlvblNob3VsZEhhbmRsZVJlb3BlbjogXCJtYWM6QXBwbGljYXRpb25TaG91bGRIYW5kbGVSZW9wZW4hXCIsXG5cdFx0V2luZG93RGlkQmVjb21lS2V5OiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dEaWRCZWNvbWVNYWluOiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVNYWluXCIsXG5cdFx0V2luZG93RGlkQmVnaW5TaGVldDogXCJtYWM6V2luZG93RGlkQmVnaW5TaGVldFwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUFscGhhOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VBbHBoYVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUJhY2tpbmdMb2NhdGlvbjogXCJtYWM6V2luZG93RGlkQ2hhbmdlQmFja2luZ0xvY2F0aW9uXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQmFja2luZ1Byb3BlcnRpZXM6IFwibWFjOldpbmRvd0RpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOldpbmRvd0RpZENoYW5nZU9jY2x1c2lvblN0YXRlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW46IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2U6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2VQcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5TcGFjZVByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTaGFyaW5nVHlwZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2hhcmluZ1R5cGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUaXRsZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVGl0bGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUb29sYmFyOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VUb29sYmFyXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd0RpZERlbWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dEaWRFbmRTaGVldDogXCJtYWM6V2luZG93RGlkRW5kU2hlZXRcIixcblx0XHRXaW5kb3dEaWRFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd0RpZEVudGVyRnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dEaWRFeGl0RnVsbFNjcmVlbjogXCJtYWM6V2luZG93RGlkRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEV4aXRWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd0RpZEV4cG9zZTogXCJtYWM6V2luZG93RGlkRXhwb3NlXCIsXG5cdFx0V2luZG93RGlkRm9jdXM6IFwibWFjOldpbmRvd0RpZEZvY3VzXCIsXG5cdFx0V2luZG93RGlkTWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJtYWM6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRPcmRlck9mZlNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd0RpZE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dEaWRSZXNpZ25LZXk6IFwibWFjOldpbmRvd0RpZFJlc2lnbktleVwiLFxuXHRcdFdpbmRvd0RpZFJlc2lnbk1haW46IFwibWFjOldpbmRvd0RpZFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwibWFjOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZTogXCJtYWM6V2luZG93RGlkVXBkYXRlXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd0RpZFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRpdGxlOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVRvb2xiYXJcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5XCIsXG5cdFx0V2luZG93U2hvdWxkQ2xvc2U6IFwibWFjOldpbmRvd1Nob3VsZENsb3NlIVwiLFxuXHRcdFdpbmRvd1dpbGxCZWNvbWVLZXk6IFwibWFjOldpbmRvd1dpbGxCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dXaWxsQmVjb21lTWFpbjogXCJtYWM6V2luZG93V2lsbEJlY29tZU1haW5cIixcblx0XHRXaW5kb3dXaWxsQmVnaW5TaGVldDogXCJtYWM6V2luZG93V2lsbEJlZ2luU2hlZXRcIixcblx0XHRXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93V2lsbENsb3NlOiBcIm1hYzpXaW5kb3dXaWxsQ2xvc2VcIixcblx0XHRXaW5kb3dXaWxsRGVtaW5pYXR1cml6ZTogXCJtYWM6V2luZG93V2lsbERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd1dpbGxFbnRlclZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEV4aXRGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyOiBcIm1hYzpXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsRm9jdXNcIixcblx0XHRXaW5kb3dXaWxsTWluaWF0dXJpemU6IFwibWFjOldpbmRvd1dpbGxNaW5pYXR1cml6ZVwiLFxuXHRcdFdpbmRvd1dpbGxNb3ZlOiBcIm1hYzpXaW5kb3dXaWxsTW92ZVwiLFxuXHRcdFdpbmRvd1dpbGxPcmRlck9mZlNjcmVlbjogXCJtYWM6V2luZG93V2lsbE9yZGVyT2ZmU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd1dpbGxPcmRlck9uU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbFJlc2lnbk1haW46IFwibWFjOldpbmRvd1dpbGxSZXNpZ25NYWluXCIsXG5cdFx0V2luZG93V2lsbFJlc2l6ZTogXCJtYWM6V2luZG93V2lsbFJlc2l6ZVwiLFxuXHRcdFdpbmRvd1dpbGxVbmZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsVW5mb2N1c1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVBbHBoYVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3I6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXM6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllc1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVTaGFkb3dcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlVGl0bGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVUb29sYmFyOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVG9vbGJhclwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd1dpbGxVc2VTdGFuZGFyZEZyYW1lOiBcIm1hYzpXaW5kb3dXaWxsVXNlU3RhbmRhcmRGcmFtZVwiLFxuXHRcdE1lbnVXaWxsT3BlbjogXCJtYWM6TWVudVdpbGxPcGVuXCIsXG5cdFx0TWVudURpZE9wZW46IFwibWFjOk1lbnVEaWRPcGVuXCIsXG5cdFx0TWVudURpZENsb3NlOiBcIm1hYzpNZW51RGlkQ2xvc2VcIixcblx0XHRNZW51V2lsbFNlbmRBY3Rpb246IFwibWFjOk1lbnVXaWxsU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVXaWxsSGlnaGxpZ2h0SXRlbTogXCJtYWM6TWVudVdpbGxIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudURpZEhpZ2hsaWdodEl0ZW06IFwibWFjOk1lbnVEaWRIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudVdpbGxEaXNwbGF5SXRlbTogXCJtYWM6TWVudVdpbGxEaXNwbGF5SXRlbVwiLFxuXHRcdE1lbnVEaWREaXNwbGF5SXRlbTogXCJtYWM6TWVudURpZERpc3BsYXlJdGVtXCIsXG5cdFx0TWVudVdpbGxBZGRJdGVtOiBcIm1hYzpNZW51V2lsbEFkZEl0ZW1cIixcblx0XHRNZW51RGlkQWRkSXRlbTogXCJtYWM6TWVudURpZEFkZEl0ZW1cIixcblx0XHRNZW51V2lsbFJlbW92ZUl0ZW06IFwibWFjOk1lbnVXaWxsUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVEaWRSZW1vdmVJdGVtOiBcIm1hYzpNZW51RGlkUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVXaWxsQmVnaW5UcmFja2luZzogXCJtYWM6TWVudVdpbGxCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudURpZEJlZ2luVHJhY2tpbmc6IFwibWFjOk1lbnVEaWRCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxFbmRUcmFja2luZzogXCJtYWM6TWVudVdpbGxFbmRUcmFja2luZ1wiLFxuXHRcdE1lbnVEaWRFbmRUcmFja2luZzogXCJtYWM6TWVudURpZEVuZFRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxVcGRhdGU6IFwibWFjOk1lbnVXaWxsVXBkYXRlXCIsXG5cdFx0TWVudURpZFVwZGF0ZTogXCJtYWM6TWVudURpZFVwZGF0ZVwiLFxuXHRcdE1lbnVXaWxsUG9wVXA6IFwibWFjOk1lbnVXaWxsUG9wVXBcIixcblx0XHRNZW51RGlkUG9wVXA6IFwibWFjOk1lbnVEaWRQb3BVcFwiLFxuXHRcdE1lbnVXaWxsU2VuZEFjdGlvblRvSXRlbTogXCJtYWM6TWVudVdpbGxTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0TWVudURpZFNlbmRBY3Rpb25Ub0l0ZW06IFwibWFjOk1lbnVEaWRTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0V2ViVmlld0RpZFN0YXJ0UHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkU3RhcnRQcm92aXNpb25hbE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZENvbW1pdE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRDb21taXROYXZpZ2F0aW9uXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZFwiLFxuXHRcdFdpbmRvd0ZpbGVEcmFnZ2luZ1BlcmZvcm1lZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nUGVyZm9ybWVkXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRXhpdGVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdFeGl0ZWRcIixcblx0fSxcblx0TGludXg6IHtcblx0XHRTeXN0ZW1UaGVtZUNoYW5nZWQ6IFwibGludXg6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdFx0V2luZG93TG9hZENoYW5nZWQ6IFwibGludXg6V2luZG93TG9hZENoYW5nZWRcIixcblx0XHRXaW5kb3dEZWxldGVFdmVudDogXCJsaW51eDpXaW5kb3dEZWxldGVFdmVudFwiLFxuXHRcdFdpbmRvd0ZvY3VzSW46IFwibGludXg6V2luZG93Rm9jdXNJblwiLFxuXHRcdFdpbmRvd0ZvY3VzT3V0OiBcImxpbnV4OldpbmRvd0ZvY3VzT3V0XCIsXG5cdFx0QXBwbGljYXRpb25TdGFydHVwOiBcImxpbnV4OkFwcGxpY2F0aW9uU3RhcnR1cFwiLFxuXHR9LFxuXHRDb21tb246IHtcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwiY29tbW9uOkFwcGxpY2F0aW9uU3RhcnRlZFwiLFxuXHRcdFdpbmRvd01heGltaXNlOiBcImNvbW1vbjpXaW5kb3dNYXhpbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWF4aW1pc2U6IFwiY29tbW9uOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcImNvbW1vbjpXaW5kb3dGdWxsc2NyZWVuXCIsXG5cdFx0V2luZG93VW5GdWxsc2NyZWVuOiBcImNvbW1vbjpXaW5kb3dVbkZ1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dSZXN0b3JlOiBcImNvbW1vbjpXaW5kb3dSZXN0b3JlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwiY29tbW9uOldpbmRvd01pbmltaXNlXCIsXG5cdFx0V2luZG93VW5NaW5pbWlzZTogXCJjb21tb246V2luZG93VW5NaW5pbWlzZVwiLFxuXHRcdFdpbmRvd0Nsb3Npbmc6IFwiY29tbW9uOldpbmRvd0Nsb3NpbmdcIixcblx0XHRXaW5kb3dab29tOiBcImNvbW1vbjpXaW5kb3dab29tXCIsXG5cdFx0V2luZG93Wm9vbUluOiBcImNvbW1vbjpXaW5kb3dab29tSW5cIixcblx0XHRXaW5kb3dab29tT3V0OiBcImNvbW1vbjpXaW5kb3dab29tT3V0XCIsXG5cdFx0V2luZG93Wm9vbVJlc2V0OiBcImNvbW1vbjpXaW5kb3dab29tUmVzZXRcIixcblx0XHRXaW5kb3dGb2N1czogXCJjb21tb246V2luZG93Rm9jdXNcIixcblx0XHRXaW5kb3dMb3N0Rm9jdXM6IFwiY29tbW9uOldpbmRvd0xvc3RGb2N1c1wiLFxuXHRcdFdpbmRvd1Nob3c6IFwiY29tbW9uOldpbmRvd1Nob3dcIixcblx0XHRXaW5kb3dIaWRlOiBcImNvbW1vbjpXaW5kb3dIaWRlXCIsXG5cdFx0V2luZG93RFBJQ2hhbmdlZDogXCJjb21tb246V2luZG93RFBJQ2hhbmdlZFwiLFxuXHRcdFdpbmRvd0ZpbGVzRHJvcHBlZDogXCJjb21tb246V2luZG93RmlsZXNEcm9wcGVkXCIsXG5cdFx0V2luZG93UnVudGltZVJlYWR5OiBcImNvbW1vbjpXaW5kb3dSdW50aW1lUmVhZHlcIixcblx0XHRUaGVtZUNoYW5nZWQ6IFwiY29tbW9uOlRoZW1lQ2hhbmdlZFwiLFxuXHR9LFxufTtcbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wZW5GaWxlRGlhbG9nT3B0aW9uc1xuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ2hvb3NlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjaG9zZW4uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DaG9vc2VGaWxlc10gLSBJbmRpY2F0ZXMgaWYgZmlsZXMgY2FuIGJlIGNob3Nlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNyZWF0ZURpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBkaXJlY3RvcmllcyBjYW4gYmUgY3JlYXRlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1Nob3dIaWRkZW5GaWxlc10gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGZpbGVzIHNob3VsZCBiZSBzaG93bi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1Jlc29sdmVzQWxpYXNlc10gLSBJbmRpY2F0ZXMgaWYgYWxpYXNlcyBzaG91bGQgYmUgcmVzb2x2ZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtBbGxvd3NNdWx0aXBsZVNlbGVjdGlvbl0gLSBJbmRpY2F0ZXMgaWYgbXVsdGlwbGUgc2VsZWN0aW9uIGlzIGFsbG93ZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtIaWRlRXh0ZW5zaW9uXSAtIEluZGljYXRlcyBpZiB0aGUgZXh0ZW5zaW9uIHNob3VsZCBiZSBoaWRkZW4uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5TZWxlY3RIaWRkZW5FeHRlbnNpb25dIC0gSW5kaWNhdGVzIGlmIGhpZGRlbiBleHRlbnNpb25zIGNhbiBiZSBzZWxlY3RlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1RyZWF0c0ZpbGVQYWNrYWdlc0FzRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGZpbGUgcGFja2FnZXMgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgZGlyZWN0b3JpZXMuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtBbGxvd3NPdGhlckZpbGV0eXBlc10gLSBJbmRpY2F0ZXMgaWYgb3RoZXIgZmlsZSB0eXBlcyBhcmUgYWxsb3dlZC5cbiAqIEBwcm9wZXJ0eSB7RmlsZUZpbHRlcltdfSBbRmlsdGVyc10gLSBBcnJheSBvZiBmaWxlIGZpbHRlcnMuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW1RpdGxlXSAtIFRpdGxlIG9mIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW01lc3NhZ2VdIC0gTWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0J1dHRvblRleHRdIC0gVGV4dCB0byBkaXNwbGF5IG9uIHRoZSBidXR0b24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0RpcmVjdG9yeV0gLSBEaXJlY3RvcnkgdG8gb3BlbiBpbiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbRGV0YWNoZWRdIC0gSW5kaWNhdGVzIGlmIHRoZSBkaWFsb2cgc2hvdWxkIGFwcGVhciBkZXRhY2hlZCBmcm9tIHRoZSBtYWluIHdpbmRvdy5cbiAqL1xuXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gU2F2ZUZpbGVEaWFsb2dPcHRpb25zXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0ZpbGVuYW1lXSAtIERlZmF1bHQgZmlsZW5hbWUgdG8gdXNlIGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DaG9vc2VEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNob3Nlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZUZpbGVzXSAtIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ3JlYXRlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbU2hvd0hpZGRlbkZpbGVzXSAtIEluZGljYXRlcyBpZiBoaWRkZW4gZmlsZXMgc2hvdWxkIGJlIHNob3duLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbUmVzb2x2ZXNBbGlhc2VzXSAtIEluZGljYXRlcyBpZiBhbGlhc2VzIHNob3VsZCBiZSByZXNvbHZlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c011bHRpcGxlU2VsZWN0aW9uXSAtIEluZGljYXRlcyBpZiBtdWx0aXBsZSBzZWxlY3Rpb24gaXMgYWxsb3dlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0hpZGVFeHRlbnNpb25dIC0gSW5kaWNhdGVzIGlmIHRoZSBleHRlbnNpb24gc2hvdWxkIGJlIGhpZGRlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhblNlbGVjdEhpZGRlbkV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGV4dGVuc2lvbnMgY2FuIGJlIHNlbGVjdGVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZmlsZSBwYWNrYWdlcyBzaG91bGQgYmUgdHJlYXRlZCBhcyBkaXJlY3Rvcmllcy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c090aGVyRmlsZXR5cGVzXSAtIEluZGljYXRlcyBpZiBvdGhlciBmaWxlIHR5cGVzIGFyZSBhbGxvd2VkLlxuICogQHByb3BlcnR5IHtGaWxlRmlsdGVyW119IFtGaWx0ZXJzXSAtIEFycmF5IG9mIGZpbGUgZmlsdGVycy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGl0bGUgb2YgdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbTWVzc2FnZV0gLSBNZXNzYWdlIHRvIHNob3cgaW4gdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbQnV0dG9uVGV4dF0gLSBUZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRGlyZWN0b3J5XSAtIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtEZXRhY2hlZF0gLSBJbmRpY2F0ZXMgaWYgdGhlIGRpYWxvZyBzaG91bGQgYXBwZWFyIGRldGFjaGVkIGZyb20gdGhlIG1haW4gd2luZG93LlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gTWVzc2FnZURpYWxvZ09wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGhlIHRpdGxlIG9mIHRoZSBkaWFsb2cgd2luZG93LlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtNZXNzYWdlXSAtIFRoZSBtYWluIG1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtCdXR0b25bXX0gW0J1dHRvbnNdIC0gQXJyYXkgb2YgYnV0dG9uIG9wdGlvbnMgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbRGV0YWNoZWRdIC0gVHJ1ZSBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cgKGlmIGFwcGxpY2FibGUpLlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gQnV0dG9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0xhYmVsXSAtIFRleHQgdGhhdCBhcHBlYXJzIHdpdGhpbiB0aGUgYnV0dG9uLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbSXNDYW5jZWxdIC0gVHJ1ZSBpZiB0aGUgYnV0dG9uIHNob3VsZCBjYW5jZWwgYW4gb3BlcmF0aW9uIHdoZW4gY2xpY2tlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0lzRGVmYXVsdF0gLSBUcnVlIGlmIHRoZSBidXR0b24gc2hvdWxkIGJlIHRoZSBkZWZhdWx0IGFjdGlvbiB3aGVuIHRoZSB1c2VyIHByZXNzZXMgZW50ZXIuXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBGaWxlRmlsdGVyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0Rpc3BsYXlOYW1lXSAtIERpc3BsYXkgbmFtZSBmb3IgdGhlIGZpbHRlciwgaXQgY291bGQgYmUgXCJUZXh0IEZpbGVzXCIsIFwiSW1hZ2VzXCIgZXRjLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtQYXR0ZXJuXSAtIFBhdHRlcm4gdG8gbWF0Y2ggZm9yIHRoZSBmaWx0ZXIsIGUuZy4gXCIqLnR4dDsqLm1kXCIgZm9yIHRleHQgbWFya2Rvd24gZmlsZXMuXG4gKi9cblxuLy8gc2V0dXBcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xud2luZG93Ll93YWlscy5kaWFsb2dFcnJvckNhbGxiYWNrID0gZGlhbG9nRXJyb3JDYWxsYmFjaztcbndpbmRvdy5fd2FpbHMuZGlhbG9nUmVzdWx0Q2FsbGJhY2sgPSBkaWFsb2dSZXN1bHRDYWxsYmFjaztcblxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuXG5pbXBvcnQgeyBuYW5vaWQgfSBmcm9tICduYW5vaWQvbm9uLXNlY3VyZSc7XG5cbi8vIERlZmluZSBjb25zdGFudHMgZnJvbSB0aGUgYG1ldGhvZHNgIG9iamVjdCBpbiBUaXRsZSBDYXNlXG5jb25zdCBEaWFsb2dJbmZvID0gMDtcbmNvbnN0IERpYWxvZ1dhcm5pbmcgPSAxO1xuY29uc3QgRGlhbG9nRXJyb3IgPSAyO1xuY29uc3QgRGlhbG9nUXVlc3Rpb24gPSAzO1xuY29uc3QgRGlhbG9nT3BlbkZpbGUgPSA0O1xuY29uc3QgRGlhbG9nU2F2ZUZpbGUgPSA1O1xuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5EaWFsb2csICcnKTtcbmNvbnN0IGRpYWxvZ1Jlc3BvbnNlcyA9IG5ldyBNYXAoKTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgaWQgdGhhdCBpcyBub3QgcHJlc2VudCBpbiBkaWFsb2dSZXNwb25zZXMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSB1bmlxdWUgaWRcbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVJRCgpIHtcbiAgICBsZXQgcmVzdWx0O1xuICAgIGRvIHtcbiAgICAgICAgcmVzdWx0ID0gbmFub2lkKCk7XG4gICAgfSB3aGlsZSAoZGlhbG9nUmVzcG9uc2VzLmhhcyhyZXN1bHQpKTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIFNob3dzIGEgZGlhbG9nIG9mIHNwZWNpZmllZCB0eXBlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gKiBAcGFyYW0ge251bWJlcn0gdHlwZSAtIHR5cGUgb2YgZGlhbG9nXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfE9wZW5GaWxlRGlhbG9nT3B0aW9uc3xTYXZlRmlsZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBvcHRpb25zIGZvciB0aGUgZGlhbG9nXG4gKiBAcmV0dXJucyB7UHJvbWlzZX0gcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggcmVzdWx0IG9mIGRpYWxvZ1xuICovXG5mdW5jdGlvbiBkaWFsb2codHlwZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgaWQgPSBnZW5lcmF0ZUlEKCk7XG4gICAgb3B0aW9uc1tcImRpYWxvZy1pZFwiXSA9IGlkO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5zZXQoaWQsIHtyZXNvbHZlLCByZWplY3R9KTtcbiAgICAgICAgY2FsbCh0eXBlLCBvcHRpb25zKS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICBkaWFsb2dSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogSGFuZGxlcyB0aGUgY2FsbGJhY2sgZnJvbSBhIGRpYWxvZy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBUaGUgSUQgb2YgdGhlIGRpYWxvZyByZXNwb25zZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhIC0gVGhlIGRhdGEgcmVjZWl2ZWQgZnJvbSB0aGUgZGlhbG9nLlxuICogQHBhcmFtIHtib29sZWFufSBpc0pTT04gLSBGbGFnIGluZGljYXRpbmcgd2hldGhlciB0aGUgZGF0YSBpcyBpbiBKU09OIGZvcm1hdC5cbiAqXG4gKiBAcmV0dXJuIHt1bmRlZmluZWR9XG4gKi9cbmZ1bmN0aW9uIGRpYWxvZ1Jlc3VsdENhbGxiYWNrKGlkLCBkYXRhLCBpc0pTT04pIHtcbiAgICBsZXQgcCA9IGRpYWxvZ1Jlc3BvbnNlcy5nZXQoaWQpO1xuICAgIGlmIChwKSB7XG4gICAgICAgIGlmIChpc0pTT04pIHtcbiAgICAgICAgICAgIHAucmVzb2x2ZShKU09OLnBhcnNlKGRhdGEpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHAucmVzb2x2ZShkYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBkaWFsb2dSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICB9XG59XG5cbi8qKlxuICogQ2FsbGJhY2sgZnVuY3Rpb24gZm9yIGhhbmRsaW5nIGVycm9ycyBpbiBkaWFsb2cuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSBkaWFsb2cgcmVzcG9uc2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIFRoZSBlcnJvciBtZXNzYWdlLlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGRpYWxvZ0Vycm9yQ2FsbGJhY2soaWQsIG1lc3NhZ2UpIHtcbiAgICBsZXQgcCA9IGRpYWxvZ1Jlc3BvbnNlcy5nZXQoaWQpO1xuICAgIGlmIChwKSB7XG4gICAgICAgIHAucmVqZWN0KG1lc3NhZ2UpO1xuICAgICAgICBkaWFsb2dSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICB9XG59XG5cblxuLy8gUmVwbGFjZSBgbWV0aG9kc2Agd2l0aCBjb25zdGFudHMgaW4gVGl0bGUgQ2FzZVxuXG4vKipcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gLSBUaGUgbGFiZWwgb2YgdGhlIGJ1dHRvbiBwcmVzc2VkXG4gKi9cbmV4cG9ydCBjb25zdCBJbmZvID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dJbmZvLCBvcHRpb25zKTtcblxuLyoqXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gVGhlIGxhYmVsIG9mIHRoZSBidXR0b24gcHJlc3NlZFxuICovXG5leHBvcnQgY29uc3QgV2FybmluZyA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nV2FybmluZywgb3B0aW9ucyk7XG5cbi8qKlxuICogQHBhcmFtIHtNZXNzYWdlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcbiAqL1xuZXhwb3J0IGNvbnN0IEVycm9yID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dFcnJvciwgb3B0aW9ucyk7XG5cbi8qKlxuICogQHBhcmFtIHtNZXNzYWdlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcbiAqL1xuZXhwb3J0IGNvbnN0IFF1ZXN0aW9uID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dRdWVzdGlvbiwgb3B0aW9ucyk7XG5cbi8qKlxuICogQHBhcmFtIHtPcGVuRmlsZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nW118c3RyaW5nPn0gUmV0dXJucyBzZWxlY3RlZCBmaWxlIG9yIGxpc3Qgb2YgZmlsZXMuIFJldHVybnMgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaXMgc2VsZWN0ZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBPcGVuRmlsZSA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nT3BlbkZpbGUsIG9wdGlvbnMpO1xuXG4vKipcbiAqIEBwYXJhbSB7U2F2ZUZpbGVEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IFJldHVybnMgdGhlIHNlbGVjdGVkIGZpbGUuIFJldHVybnMgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaXMgc2VsZWN0ZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBTYXZlRmlsZSA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nU2F2ZUZpbGUsIG9wdGlvbnMpO1xuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQgeyBuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lcyB9IGZyb20gXCIuL3J1bnRpbWVcIjtcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZC9ub24tc2VjdXJlJztcblxuLy8gU2V0dXBcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xud2luZG93Ll93YWlscy5jYWxsUmVzdWx0SGFuZGxlciA9IHJlc3VsdEhhbmRsZXI7XG53aW5kb3cuX3dhaWxzLmNhbGxFcnJvckhhbmRsZXIgPSBlcnJvckhhbmRsZXI7XG5cblxuY29uc3QgQ2FsbEJpbmRpbmcgPSAwO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ2FsbCwgJycpO1xuY29uc3QgY2FuY2VsQ2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ2FuY2VsQ2FsbCwgJycpO1xubGV0IGNhbGxSZXNwb25zZXMgPSBuZXcgTWFwKCk7XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgdW5pcXVlIElEIHVzaW5nIHRoZSBuYW5vaWQgbGlicmFyeS5cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IC0gQSB1bmlxdWUgSUQgdGhhdCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgY2FsbFJlc3BvbnNlcyBzZXQuXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlSUQoKSB7XG4gICAgbGV0IHJlc3VsdDtcbiAgICBkbyB7XG4gICAgICAgIHJlc3VsdCA9IG5hbm9pZCgpO1xuICAgIH0gd2hpbGUgKGNhbGxSZXNwb25zZXMuaGFzKHJlc3VsdCkpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogSGFuZGxlcyB0aGUgcmVzdWx0IG9mIGEgY2FsbCByZXF1ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFRoZSBpZCBvZiB0aGUgcmVxdWVzdCB0byBoYW5kbGUgdGhlIHJlc3VsdCBmb3IuXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YSAtIFRoZSByZXN1bHQgZGF0YSBvZiB0aGUgcmVxdWVzdC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNKU09OIC0gSW5kaWNhdGVzIHdoZXRoZXIgdGhlIGRhdGEgaXMgSlNPTiBvciBub3QuXG4gKlxuICogQHJldHVybiB7dW5kZWZpbmVkfSAtIFRoaXMgbWV0aG9kIGRvZXMgbm90IHJldHVybiBhbnkgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIHJlc3VsdEhhbmRsZXIoaWQsIGRhdGEsIGlzSlNPTikge1xuICAgIGNvbnN0IHByb21pc2VIYW5kbGVyID0gZ2V0QW5kRGVsZXRlUmVzcG9uc2UoaWQpO1xuICAgIGlmIChwcm9taXNlSGFuZGxlcikge1xuICAgICAgICBwcm9taXNlSGFuZGxlci5yZXNvbHZlKGlzSlNPTiA/IEpTT04ucGFyc2UoZGF0YSkgOiBkYXRhKTtcbiAgICB9XG59XG5cbi8qKlxuICogSGFuZGxlcyB0aGUgZXJyb3IgZnJvbSBhIGNhbGwgcmVxdWVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBUaGUgaWQgb2YgdGhlIHByb21pc2UgaGFuZGxlci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UgdG8gcmVqZWN0IHRoZSBwcm9taXNlIGhhbmRsZXIgd2l0aC5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5mdW5jdGlvbiBlcnJvckhhbmRsZXIoaWQsIG1lc3NhZ2UpIHtcbiAgICBjb25zdCBwcm9taXNlSGFuZGxlciA9IGdldEFuZERlbGV0ZVJlc3BvbnNlKGlkKTtcbiAgICBpZiAocHJvbWlzZUhhbmRsZXIpIHtcbiAgICAgICAgcHJvbWlzZUhhbmRsZXIucmVqZWN0KG1lc3NhZ2UpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZXRyaWV2ZXMgYW5kIHJlbW92ZXMgdGhlIHJlc3BvbnNlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gSUQgZnJvbSB0aGUgY2FsbFJlc3BvbnNlcyBtYXAuXG4gKlxuICogQHBhcmFtIHthbnl9IGlkIC0gVGhlIElEIG9mIHRoZSByZXNwb25zZSB0byBiZSByZXRyaWV2ZWQgYW5kIHJlbW92ZWQuXG4gKlxuICogQHJldHVybnMge2FueX0gVGhlIHJlc3BvbnNlIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIElELlxuICovXG5mdW5jdGlvbiBnZXRBbmREZWxldGVSZXNwb25zZShpZCkge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gY2FsbFJlc3BvbnNlcy5nZXQoaWQpO1xuICAgIGNhbGxSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICByZXR1cm4gcmVzcG9uc2U7XG59XG5cbi8qKlxuICogRXhlY3V0ZXMgYSBjYWxsIHVzaW5nIHRoZSBwcm92aWRlZCB0eXBlIGFuZCBvcHRpb25zLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gdHlwZSAtIFRoZSB0eXBlIG9mIGNhbGwgdG8gZXhlY3V0ZS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gLSBBZGRpdGlvbmFsIG9wdGlvbnMgZm9yIHRoZSBjYWxsLlxuICogQHJldHVybiB7UHJvbWlzZX0gLSBBIHByb21pc2UgdGhhdCB3aWxsIGJlIHJlc29sdmVkIG9yIHJlamVjdGVkIGJhc2VkIG9uIHRoZSByZXN1bHQgb2YgdGhlIGNhbGwuIEl0IGFsc28gaGFzIGEgY2FuY2VsIG1ldGhvZCB0byBjYW5jZWwgYSBsb25nIHJ1bm5pbmcgcmVxdWVzdC5cbiAqL1xuZnVuY3Rpb24gY2FsbEJpbmRpbmcodHlwZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgaWQgPSBnZW5lcmF0ZUlEKCk7XG4gICAgY29uc3QgZG9DYW5jZWwgPSAoKSA9PiB7IGNhbmNlbENhbGwodHlwZSwge1wiY2FsbC1pZFwiOiBpZH0pIH07XG4gICAgdmFyIHF1ZXVlZENhbmNlbCA9IGZhbHNlLCBjYWxsUnVubmluZyA9IGZhbHNlO1xuICAgIHZhciBwID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBvcHRpb25zW1wiY2FsbC1pZFwiXSA9IGlkO1xuICAgICAgICBjYWxsUmVzcG9uc2VzLnNldChpZCwgeyByZXNvbHZlLCByZWplY3QgfSk7XG4gICAgICAgIGNhbGwodHlwZSwgb3B0aW9ucykuXG4gICAgICAgICAgICB0aGVuKChfKSA9PiB7XG4gICAgICAgICAgICAgICAgY2FsbFJ1bm5pbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGlmIChxdWV1ZWRDYW5jZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9DYW5jZWwoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5cbiAgICAgICAgICAgIGNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgY2FsbFJlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgICAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgcC5jYW5jZWwgPSAoKSA9PiB7XG4gICAgICAgIGlmIChjYWxsUnVubmluZykge1xuICAgICAgICAgICAgZG9DYW5jZWwoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHF1ZXVlZENhbmNlbCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFxuICAgIHJldHVybiBwO1xufVxuXG4vKipcbiAqIENhbGwgbWV0aG9kLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gVGhlIG9wdGlvbnMgZm9yIHRoZSBtZXRob2QuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSAtIFRoZSByZXN1bHQgb2YgdGhlIGNhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDYWxsKG9wdGlvbnMpIHtcbiAgICByZXR1cm4gY2FsbEJpbmRpbmcoQ2FsbEJpbmRpbmcsIG9wdGlvbnMpO1xufVxuXG4vKipcbiAqIEV4ZWN1dGVzIGEgbWV0aG9kIGJ5IG5hbWUuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIGluIHRoZSBmb3JtYXQgJ3BhY2thZ2Uuc3RydWN0Lm1ldGhvZCcuXG4gKiBAcGFyYW0gey4uLip9IGFyZ3MgLSBUaGUgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIG1ldGhvZC5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgbmFtZSBpcyBub3QgYSBzdHJpbmcgb3IgaXMgbm90IGluIHRoZSBjb3JyZWN0IGZvcm1hdC5cbiAqIEByZXR1cm5zIHsqfSBUaGUgcmVzdWx0IG9mIHRoZSBtZXRob2QgZXhlY3V0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQnlOYW1lKG5hbWUsIC4uLmFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIG5hbWUgIT09IFwic3RyaW5nXCIgfHwgbmFtZS5zcGxpdChcIi5cIikubGVuZ3RoICE9PSAzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbGxCeU5hbWUgcmVxdWlyZXMgYSBzdHJpbmcgaW4gdGhlIGZvcm1hdCAncGFja2FnZS5zdHJ1Y3QubWV0aG9kJ1wiKTtcbiAgICB9XG4gICAgbGV0IFtwYWNrYWdlTmFtZSwgc3RydWN0TmFtZSwgbWV0aG9kTmFtZV0gPSBuYW1lLnNwbGl0KFwiLlwiKTtcbiAgICByZXR1cm4gY2FsbEJpbmRpbmcoQ2FsbEJpbmRpbmcsIHtcbiAgICAgICAgcGFja2FnZU5hbWUsXG4gICAgICAgIHN0cnVjdE5hbWUsXG4gICAgICAgIG1ldGhvZE5hbWUsXG4gICAgICAgIGFyZ3NcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBDYWxscyBhIG1ldGhvZCBieSBpdHMgSUQgd2l0aCB0aGUgc3BlY2lmaWVkIGFyZ3VtZW50cy5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gbWV0aG9kSUQgLSBUaGUgSUQgb2YgdGhlIG1ldGhvZCB0byBjYWxsLlxuICogQHBhcmFtIHsuLi4qfSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXG4gKiBAcmV0dXJuIHsqfSAtIFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQnlJRChtZXRob2RJRCwgLi4uYXJncykge1xuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywge1xuICAgICAgICBtZXRob2RJRCxcbiAgICAgICAgYXJnc1xuICAgIH0pO1xufVxuXG4vKipcbiAqIENhbGxzIGEgbWV0aG9kIG9uIGEgcGx1Z2luLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBwbHVnaW5OYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHBsdWdpbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2ROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIG1ldGhvZCB0byBjYWxsLlxuICogQHBhcmFtIHsuLi4qfSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXG4gKiBAcmV0dXJucyB7Kn0gLSBUaGUgcmVzdWx0IG9mIHRoZSBtZXRob2QgY2FsbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFBsdWdpbihwbHVnaW5OYW1lLCBtZXRob2ROYW1lLCAuLi5hcmdzKSB7XG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XG4gICAgICAgIHBhY2thZ2VOYW1lOiBcIndhaWxzLXBsdWdpbnNcIixcbiAgICAgICAgc3RydWN0TmFtZTogcGx1Z2luTmFtZSxcbiAgICAgICAgbWV0aG9kTmFtZSxcbiAgICAgICAgYXJnc1xuICAgIH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQge2RlYnVnTG9nfSBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvbG9nXCI7XG5cbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xuXG5pbXBvcnQgKiBhcyBBcHBsaWNhdGlvbiBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb25cIjtcbmltcG9ydCAqIGFzIEJyb3dzZXIgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXJcIjtcbmltcG9ydCAqIGFzIENsaXBib2FyZCBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvY2xpcGJvYXJkXCI7XG5pbXBvcnQgKiBhcyBDb250ZXh0TWVudSBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvY29udGV4dG1lbnVcIjtcbmltcG9ydCAqIGFzIERyYWcgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RyYWdcIjtcbmltcG9ydCAqIGFzIEZsYWdzIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9mbGFnc1wiO1xuaW1wb3J0ICogYXMgU2NyZWVucyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvc2NyZWVuc1wiO1xuaW1wb3J0ICogYXMgU3lzdGVtIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9zeXN0ZW1cIjtcbmltcG9ydCAqIGFzIFdpbmRvdyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvd2luZG93XCI7XG5pbXBvcnQgKiBhcyBXTUwgZnJvbSAnLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvd21sJztcbmltcG9ydCAqIGFzIEV2ZW50cyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZXZlbnRzXCI7XG5pbXBvcnQgKiBhcyBEaWFsb2dzIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9kaWFsb2dzXCI7XG5pbXBvcnQgKiBhcyBDYWxsIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxsc1wiO1xuaW1wb3J0IHtpbnZva2V9IGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9zeXN0ZW1cIjtcblxuLyoqKlxuIFRoaXMgdGVjaG5pcXVlIGZvciBwcm9wZXIgbG9hZCBkZXRlY3Rpb24gaXMgdGFrZW4gZnJvbSBIVE1YOlxuXG4gQlNEIDItQ2xhdXNlIExpY2Vuc2VcblxuIENvcHlyaWdodCAoYykgMjAyMCwgQmlnIFNreSBTb2Z0d2FyZVxuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cbiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXRcbiBtb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuIDEuIFJlZGlzdHJpYnV0aW9ucyBvZiBzb3VyY2UgY29kZSBtdXN0IHJldGFpbiB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSwgdGhpc1xuIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuXG4gMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cblxuIFRISVMgU09GVFdBUkUgSVMgUFJPVklERUQgQlkgVEhFIENPUFlSSUdIVCBIT0xERVJTIEFORCBDT05UUklCVVRPUlMgXCJBUyBJU1wiXG4gQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRVxuIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkgQU5EIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFSRVxuIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBDT1BZUklHSFQgSE9MREVSIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEVcbiBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTFxuIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTIE9SXG4gU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVJcbiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLFxuIE9SIFRPUlQgKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSkgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFXG4gT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cblxuICoqKi9cblxud2luZG93Ll93YWlscy5pbnZva2U9aW52b2tlO1xuXG53aW5kb3cud2FpbHMgPSB3aW5kb3cud2FpbHMgfHwge307XG53aW5kb3cud2FpbHMuQXBwbGljYXRpb24gPSBBcHBsaWNhdGlvbjtcbndpbmRvdy53YWlscy5Ccm93c2VyID0gQnJvd3NlcjtcbndpbmRvdy53YWlscy5DYWxsID0gQ2FsbDtcbndpbmRvdy53YWlscy5DbGlwYm9hcmQgPSBDbGlwYm9hcmQ7XG53aW5kb3cud2FpbHMuRGlhbG9ncyA9IERpYWxvZ3M7XG53aW5kb3cud2FpbHMuRXZlbnRzID0gRXZlbnRzO1xud2luZG93LndhaWxzLkZsYWdzID0gRmxhZ3M7XG53aW5kb3cud2FpbHMuU2NyZWVucyA9IFNjcmVlbnM7XG53aW5kb3cud2FpbHMuU3lzdGVtID0gU3lzdGVtO1xud2luZG93LndhaWxzLldpbmRvdyA9IFdpbmRvdztcbndpbmRvdy53YWlscy5XTUwgPSBXTUw7XG5cblxubGV0IGlzUmVhZHkgPSBmYWxzZVxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGZ1bmN0aW9uKCkge1xuICAgIGlzUmVhZHkgPSB0cnVlXG4gICAgd2luZG93Ll93YWlscy5pbnZva2UoJ3dhaWxzOnJ1bnRpbWU6cmVhZHknKTtcbiAgICBpZihERUJVRykge1xuICAgICAgICBkZWJ1Z0xvZyhcIldhaWxzIFJ1bnRpbWUgTG9hZGVkXCIpO1xuICAgIH1cbn0pXG5cbmZ1bmN0aW9uIHdoZW5SZWFkeShmbikge1xuICAgIGlmIChpc1JlYWR5IHx8IGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdjb21wbGV0ZScpIHtcbiAgICAgICAgZm4oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgZm4pO1xuICAgIH1cbn1cblxud2hlblJlYWR5KCgpID0+IHtcbiAgICBXTUwuUmVsb2FkKCk7XG59KTtcbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7O0FBS08sV0FBUyxTQUFTLFNBQVM7QUFFOUIsWUFBUTtBQUFBLE1BQ0osa0JBQWtCLFVBQVU7QUFBQSxNQUM1QjtBQUFBLE1BQ0E7QUFBQSxJQUNKO0FBQUEsRUFDSjs7O0FDWkE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7QUNBQSxNQUFJLGNBQ0Y7QUFXSyxNQUFJLFNBQVMsQ0FBQ0EsUUFBTyxPQUFPO0FBQ2pDLFFBQUksS0FBSztBQUNULFFBQUksSUFBSUE7QUFDUixXQUFPLEtBQUs7QUFDVixZQUFNLFlBQWEsS0FBSyxPQUFPLElBQUksS0FBTSxDQUFDO0FBQUEsSUFDNUM7QUFDQSxXQUFPO0FBQUEsRUFDVDs7O0FDTkEsTUFBTSxhQUFhLE9BQU8sU0FBUyxTQUFTO0FBR3JDLE1BQU0sY0FBYztBQUFBLElBQ3ZCLE1BQU07QUFBQSxJQUNOLFdBQVc7QUFBQSxJQUNYLGFBQWE7QUFBQSxJQUNiLFFBQVE7QUFBQSxJQUNSLGFBQWE7QUFBQSxJQUNiLFFBQVE7QUFBQSxJQUNSLFFBQVE7QUFBQSxJQUNSLFNBQVM7QUFBQSxJQUNULFFBQVE7QUFBQSxJQUNSLFNBQVM7QUFBQSxJQUNULFlBQVk7QUFBQSxFQUNoQjtBQUNPLE1BQUksV0FBVyxPQUFPO0FBc0J0QixXQUFTLHVCQUF1QixRQUFRLFlBQVk7QUFDdkQsV0FBTyxTQUFVLFFBQVEsT0FBSyxNQUFNO0FBQ2hDLGFBQU8sa0JBQWtCLFFBQVEsUUFBUSxZQUFZLElBQUk7QUFBQSxJQUM3RDtBQUFBLEVBQ0o7QUFxQ0EsV0FBUyxrQkFBa0IsVUFBVSxRQUFRLFlBQVksTUFBTTtBQUMzRCxRQUFJLE1BQU0sSUFBSSxJQUFJLFVBQVU7QUFDNUIsUUFBSSxhQUFhLE9BQU8sVUFBVSxRQUFRO0FBQzFDLFFBQUksYUFBYSxPQUFP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O0FBQzNCLFNBQU8sTUFBTSxVQUFVO0FBQ3ZCLFNBQU8sTUFBTSxPQUFPO0FBQ3BCLFNBQU8sTUFBTSxZQUFZO0FBQ3pCLFNBQU8sTUFBTSxVQUFVO0FBQ3ZCLFNBQU8sTUFBTSxTQUFTO0FBQ3RCLFNBQU8sTUFBTSxRQUFRO0FBQ3JCLFNBQU8sTUFBTSxVQUFVO0FBQ3ZCLFNBQU8sTUFBTSxTQUFTO0FBQ3RCLFNBQU8sTUFBTSxTQUFTO0FBQ3RCLFNBQU8sTUFBTSxNQUFNO0FBR25CLE1BQUksVUFBVTtBQUNkLFdBQVMsaUJBQWlCLG9CQUFvQixXQUFXO0FBQ3JELGNBQVU7QUFDVixXQUFPLE9BQU8sT0FBTyxxQkFBcUI7QUFDMUMsUUFBRyxNQUFPO0FBQ04sZUFBUyxzQkFBc0I7QUFBQSxJQUNuQztBQUFBLEVBQ0osQ0FBQztBQUVELFdBQVMsVUFBVSxJQUFJO0FBQ25CLFFBQUksV0FBVyxTQUFTLGVBQWUsWUFBWTtBQUMvQyxTQUFHO0FBQUEsSUFDUCxPQUFPO0FBQ0gsZUFBUyxpQkFBaUIsb0JBQW9CLEVBQUU7QUFBQSxJQUNwRDtBQUFBLEVBQ0o7QUFFQSxZQUFVLE1BQU07QUFDWixJQUFJLE9BQU87QUFBQSxFQUNmLENBQUM7IiwKICAibmFtZXMiOiBbInNpemUiLCAiY2FsbCIsICJjYWxsIiwgImNhbGwiLCAiY2FsbCIsICJjYWxsIiwgIkhpZGUiLCAiU2hvdyIsICJzZXRSZXNpemFibGUiLCAiY2FsbCIsICJ3aWR0aCIsICJoZWlnaHQiLCAicmVzaXphYmxlIiwgIkhpZGUiLCAiU2hvdyIsICJjYWxsIiwgImV2ZW50TmFtZSIsICJFcnJvciIsICJjYWxsIiwgIkVycm9yIiwgImNhbGwiLCAiZ2VuZXJhdGVJRCJdCn0K diff --git a/v3/internal/assetserver/assets/runtime.js b/v3/internal/assetserver/assets/runtime.js new file mode 100644 index 00000000000..f2e675a5716 --- /dev/null +++ b/v3/internal/assetserver/assets/runtime.js @@ -0,0 +1 @@ +(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9,CancelCall:10},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,m)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();m(Error(c.statusText))}).then(c=>s(c)).catch(c=>m(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var Q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return Q(Ce,{text:e})}function Me(){return Q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function W(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,qe=1,Qe=2;function Je(){return k(Xe)}function $e(){return k(qe)}function ei(){return k(Qe)}var H={};w(H,{Center:()=>Oi,Close:()=>qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>Qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function qi(){r.Close()}function Qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,u=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=u.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?u.delete(e.name):u.set(e.name,i))}}function _(e,i,n){let o=u.get(e)||[],t=new V(e,i,n);return o.push(t),u.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=u.get(i).filter(o=>o!==e);n.length===0?u.delete(i):u.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>u.delete(o))}function gn(){u.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),g=new Map;function An(){let e;do e=f();while(g.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{g.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),g.delete(n)})})}function vn(e,i,n){let o=g.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),g.delete(e))}function bn(e,i){let n=g.get(e);n&&(n.reject(i),g.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(m){m!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>_n,ByName:()=>Vn,Call:()=>Hn,Plugin:()=>Zn});window._wails=window._wails||{};window._wails.callResultHandler=kn;window._wails.callErrorHandler=Nn;var y=0,Fn=l(d.Call,""),Ln=l(d.CancelCall,""),v=new Map;function zn(){let e;do e=f();while(v.has(e));return e}function kn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function Nn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){let n=zn(),o=()=>{Ln(e,{"call-id":n})};var t=!1,a=!1,s=new Promise((m,c)=>{i["call-id"]=n,v.set(n,{resolve:m,reject:c}),Fn(e,i).then(p=>{a=!0,t&&o()}).catch(p=>{c(p),v.delete(n)})});return s.cancel=()=>{a?o():t=!0},s}function Hn(e){return O(y,e)}function Vn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function _n(e,...i){return O(y,{methodID:e,args:i})}function Zn(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function jn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}jn(()=>{Y()});})(); diff --git a/v3/internal/assetserver/bundled_assetserver.go b/v3/internal/assetserver/bundled_assetserver.go new file mode 100644 index 00000000000..15297cd3702 --- /dev/null +++ b/v3/internal/assetserver/bundled_assetserver.go @@ -0,0 +1,33 @@ +package assetserver + +import ( + "github.com/wailsapp/wails/v3/internal/assetserver/bundledassets" + "io/fs" + "net/http" + "strings" +) + +type BundledAssetServer struct { + handler http.Handler +} + +func NewBundledAssetFileServer(fs fs.FS) *BundledAssetServer { + return &BundledAssetServer{ + handler: NewAssetFileServer(fs), + } +} + +func (b *BundledAssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + if strings.HasPrefix(req.URL.Path, "/wails/") { + // Strip the /wails prefix + req.URL.Path = req.URL.Path[6:] + switch req.URL.Path { + case "/runtime.js": + rw.Header().Set("Content-Type", "application/javascript") + rw.Write([]byte(bundledassets.RuntimeJS)) + return + } + return + } + b.handler.ServeHTTP(rw, req) +} diff --git a/v3/examples/window-api/assets/runtime.debug.js b/v3/internal/assetserver/bundledassets/runtime.debug.js similarity index 100% rename from v3/examples/window-api/assets/runtime.debug.js rename to v3/internal/assetserver/bundledassets/runtime.debug.js diff --git a/v3/examples/window-api/assets/runtime.js b/v3/internal/assetserver/bundledassets/runtime.js similarity index 100% rename from v3/examples/window-api/assets/runtime.js rename to v3/internal/assetserver/bundledassets/runtime.js diff --git a/v3/internal/commands/build_assets/runtime/compiled.go b/v3/internal/assetserver/bundledassets/runtime_dev.go similarity index 51% rename from v3/internal/commands/build_assets/runtime/compiled.go rename to v3/internal/assetserver/bundledassets/runtime_dev.go index f7dea63c625..2c9621a667c 100644 --- a/v3/internal/commands/build_assets/runtime/compiled.go +++ b/v3/internal/assetserver/bundledassets/runtime_dev.go @@ -1,9 +1,8 @@ -package runtime +//go:build !production -import _ "embed" +package bundledassets -//go:embed runtime.js -var RuntimeJS []byte +import _ "embed" //go:embed runtime.debug.js -var RuntimeDebugJS []byte +var RuntimeJS []byte diff --git a/v3/internal/assetserver/bundledassets/runtime_production.go b/v3/internal/assetserver/bundledassets/runtime_production.go new file mode 100644 index 00000000000..9614a7b13bf --- /dev/null +++ b/v3/internal/assetserver/bundledassets/runtime_production.go @@ -0,0 +1,8 @@ +//go:build production + +package bundledassets + +import _ "embed" + +//go:embed runtime.js +var RuntimeJS []byte diff --git a/v3/internal/commands/build_assets/runtime/runtime.debug.js b/v3/internal/commands/build_assets/runtime/runtime.debug.js deleted file mode 100644 index 834309aac4c..00000000000 --- a/v3/internal/commands/build_assets/runtime/runtime.debug.js +++ /dev/null @@ -1,1139 +0,0 @@ -(() => { - var __defProp = Object.defineProperty; - var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); - }; - - // desktop/@wailsio/runtime/src/log.js - function debugLog(message) { - console.log( - "%c wails3 %c " + message + " ", - "background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem", - "background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem" - ); - } - - // desktop/@wailsio/runtime/src/application.js - var application_exports = {}; - __export(application_exports, { - Hide: () => Hide, - Quit: () => Quit, - Show: () => Show - }); - - // node_modules/nanoid/non-secure/index.js - var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"; - var nanoid = (size2 = 21) => { - let id = ""; - let i = size2; - while (i--) { - id += urlAlphabet[Math.random() * 64 | 0]; - } - return id; - }; - - // desktop/@wailsio/runtime/src/runtime.js - var runtimeURL = window.location.origin + "/wails/runtime"; - var objectNames = { - Call: 0, - Clipboard: 1, - Application: 2, - Events: 3, - ContextMenu: 4, - Dialog: 5, - Window: 6, - Screens: 7, - System: 8, - Browser: 9, - CancelCall: 10 - }; - var clientId = nanoid(); - function newRuntimeCallerWithID(object, windowName) { - return function(method, args = null) { - return runtimeCallWithID(object, method, windowName, args); - }; - } - function runtimeCallWithID(objectID, method, windowName, args) { - let url = new URL(runtimeURL); - url.searchParams.append("object", objectID); - url.searchParams.append("method", method); - let fetchOptions = { - headers: {} - }; - if (windowName) { - fetchOptions.headers["x-wails-window-name"] = windowName; - } - if (args) { - url.searchParams.append("args", JSON.stringify(args)); - } - fetchOptions.headers["x-wails-client-id"] = clientId; - return new Promise((resolve, reject) => { - fetch(url, fetchOptions).then((response) => { - if (response.ok) { - if (response.headers.get("Content-Type") && response.headers.get("Content-Type").indexOf("application/json") !== -1) { - return response.json(); - } else { - return response.text(); - } - } - reject(Error(response.statusText)); - }).then((data) => resolve(data)).catch((error) => reject(error)); - }); - } - - // desktop/@wailsio/runtime/src/application.js - var call = newRuntimeCallerWithID(objectNames.Application, ""); - var HideMethod = 0; - var ShowMethod = 1; - var QuitMethod = 2; - function Hide() { - return call(HideMethod); - } - function Show() { - return call(ShowMethod); - } - function Quit() { - return call(QuitMethod); - } - - // desktop/@wailsio/runtime/src/browser.js - var browser_exports = {}; - __export(browser_exports, { - OpenURL: () => OpenURL - }); - var call2 = newRuntimeCallerWithID(objectNames.Browser, ""); - var BrowserOpenURL = 0; - function OpenURL(url) { - return call2(BrowserOpenURL, { url }); - } - - // desktop/@wailsio/runtime/src/clipboard.js - var clipboard_exports = {}; - __export(clipboard_exports, { - SetText: () => SetText, - Text: () => Text - }); - var call3 = newRuntimeCallerWithID(objectNames.Clipboard, ""); - var ClipboardSetText = 0; - var ClipboardText = 1; - function SetText(text) { - return call3(ClipboardSetText, { text }); - } - function Text() { - return call3(ClipboardText); - } - - // desktop/@wailsio/runtime/src/system.js - var system_exports = {}; - __export(system_exports, { - Capabilities: () => Capabilities, - Environment: () => Environment, - IsAMD64: () => IsAMD64, - IsARM: () => IsARM, - IsARM64: () => IsARM64, - IsDarkMode: () => IsDarkMode, - IsDebug: () => IsDebug, - IsLinux: () => IsLinux, - IsMac: () => IsMac, - IsWindows: () => IsWindows, - invoke: () => invoke - }); - var call4 = newRuntimeCallerWithID(objectNames.System, ""); - var systemIsDarkMode = 0; - var environment = 1; - function invoke(msg) { - if (window.chrome) { - return window.chrome.webview.postMessage(msg); - } - return window.webkit.messageHandlers.external.postMessage(msg); - } - function IsDarkMode() { - return call4(systemIsDarkMode); - } - function Capabilities() { - let response = fetch("/wails/capabilities"); - return response.json(); - } - function Environment() { - return call4(environment); - } - function IsWindows() { - return window._wails.environment.OS === "windows"; - } - function IsLinux() { - return window._wails.environment.OS === "linux"; - } - function IsMac() { - return window._wails.environment.OS === "darwin"; - } - function IsAMD64() { - return window._wails.environment.Arch === "amd64"; - } - function IsARM() { - return window._wails.environment.Arch === "arm"; - } - function IsARM64() { - return window._wails.environment.Arch === "arm64"; - } - function IsDebug() { - return window._wails.environment.Debug === true; - } - - // desktop/@wailsio/runtime/src/contextmenu.js - window.addEventListener("contextmenu", contextMenuHandler); - var call5 = newRuntimeCallerWithID(objectNames.ContextMenu, ""); - var ContextMenuOpen = 0; - function openContextMenu(id, x, y, data) { - void call5(ContextMenuOpen, { id, x, y, data }); - } - function contextMenuHandler(event) { - let element = event.target; - let customContextMenu = window.getComputedStyle(element).getPropertyValue("--custom-contextmenu"); - customContextMenu = customContextMenu ? customContextMenu.trim() : ""; - if (customContextMenu) { - event.preventDefault(); - let customContextMenuData = window.getComputedStyle(element).getPropertyValue("--custom-contextmenu-data"); - openContextMenu(customContextMenu, event.clientX, event.clientY, customContextMenuData); - return; - } - processDefaultContextMenu(event); - } - function processDefaultContextMenu(event) { - if (IsDebug()) { - return; - } - const element = event.target; - const computedStyle = window.getComputedStyle(element); - const defaultContextMenuAction = computedStyle.getPropertyValue("--default-contextmenu").trim(); - switch (defaultContextMenuAction) { - case "show": - return; - case "hide": - event.preventDefault(); - return; - default: - if (element.isContentEditable) { - return; - } - const selection = window.getSelection(); - const hasSelection = selection.toString().length > 0; - if (hasSelection) { - for (let i = 0; i < selection.rangeCount; i++) { - const range = selection.getRangeAt(i); - const rects = range.getClientRects(); - for (let j = 0; j < rects.length; j++) { - const rect = rects[j]; - if (document.elementFromPoint(rect.left, rect.top) === element) { - return; - } - } - } - } - if (element.tagName === "INPUT" || element.tagName === "TEXTAREA") { - if (hasSelection || !element.readOnly && !element.disabled) { - return; - } - } - event.preventDefault(); - } - } - - // desktop/@wailsio/runtime/src/flags.js - var flags_exports = {}; - __export(flags_exports, { - GetFlag: () => GetFlag - }); - function GetFlag(keyString) { - try { - return window._wails.flags[keyString]; - } catch (e) { - throw new Error("Unable to retrieve flag '" + keyString + "': " + e); - } - } - - // desktop/@wailsio/runtime/src/drag.js - window._wails = window._wails || {}; - window._wails.setResizable = setResizable; - window._wails.endDrag = endDrag; - window.addEventListener("mousedown", onMouseDown); - window.addEventListener("mousemove", onMouseMove); - window.addEventListener("mouseup", onMouseUp); - var shouldDrag = false; - var resizeEdge = null; - var resizable = false; - var defaultCursor = "auto"; - function dragTest(e) { - let val = window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region"); - if (!val || val === "" || val.trim() !== "drag" || e.buttons !== 1) { - return false; - } - return e.detail === 1; - } - function setResizable(value) { - resizable = value; - } - function endDrag() { - document.body.style.cursor = "default"; - shouldDrag = false; - } - function testResize() { - if (resizeEdge) { - invoke(`resize:${resizeEdge}`); - return true; - } - return false; - } - function onMouseDown(e) { - if (IsWindows() && testResize() || dragTest(e)) { - shouldDrag = !!isValidDrag(e); - } - } - function isValidDrag(e) { - return !(e.offsetX > e.target.clientWidth || e.offsetY > e.target.clientHeight); - } - function onMouseUp(e) { - let mousePressed = e.buttons !== void 0 ? e.buttons : e.which; - if (mousePressed > 0) { - endDrag(); - } - } - function setResize(cursor = defaultCursor) { - document.documentElement.style.cursor = cursor; - resizeEdge = cursor; - } - function onMouseMove(e) { - shouldDrag = checkDrag(e); - if (IsWindows() && resizable) { - handleResize(e); - } - } - function checkDrag(e) { - let mousePressed = e.buttons !== void 0 ? e.buttons : e.which; - if (shouldDrag && mousePressed > 0) { - invoke("drag"); - return false; - } - return shouldDrag; - } - function handleResize(e) { - let resizeHandleHeight = GetFlag("system.resizeHandleHeight") || 5; - let resizeHandleWidth = GetFlag("system.resizeHandleWidth") || 5; - let cornerExtra = GetFlag("resizeCornerExtra") || 10; - let rightBorder = window.outerWidth - e.clientX < resizeHandleWidth; - let leftBorder = e.clientX < resizeHandleWidth; - let topBorder = e.clientY < resizeHandleHeight; - let bottomBorder = window.outerHeight - e.clientY < resizeHandleHeight; - let rightCorner = window.outerWidth - e.clientX < resizeHandleWidth + cornerExtra; - let leftCorner = e.clientX < resizeHandleWidth + cornerExtra; - let topCorner = e.clientY < resizeHandleHeight + cornerExtra; - let bottomCorner = window.outerHeight - e.clientY < resizeHandleHeight + cornerExtra; - if (!leftBorder && !rightBorder && !topBorder && !bottomBorder && resizeEdge !== void 0) { - setResize(); - } else if (rightCorner && bottomCorner) - setResize("se-resize"); - else if (leftCorner && bottomCorner) - setResize("sw-resize"); - else if (leftCorner && topCorner) - setResize("nw-resize"); - else if (topCorner && rightCorner) - setResize("ne-resize"); - else if (leftBorder) - setResize("w-resize"); - else if (topBorder) - setResize("n-resize"); - else if (bottomBorder) - setResize("s-resize"); - else if (rightBorder) - setResize("e-resize"); - } - - // desktop/@wailsio/runtime/src/screens.js - var screens_exports = {}; - __export(screens_exports, { - GetAll: () => GetAll, - GetCurrent: () => GetCurrent, - GetPrimary: () => GetPrimary - }); - var call6 = newRuntimeCallerWithID(objectNames.Screens, ""); - var getAll = 0; - var getPrimary = 1; - var getCurrent = 2; - function GetAll() { - return call6(getAll); - } - function GetPrimary() { - return call6(getPrimary); - } - function GetCurrent() { - return call6(getCurrent); - } - - // desktop/@wailsio/runtime/src/window.js - var window_exports = {}; - __export(window_exports, { - Center: () => Center, - Close: () => Close, - Fullscreen: () => Fullscreen, - Get: () => Get, - GetZoomLevel: () => GetZoomLevel, - Height: () => Height, - Hide: () => Hide2, - Maximise: () => Maximise, - Minimise: () => Minimise, - RelativePosition: () => RelativePosition, - Restore: () => Restore, - Screen: () => Screen, - SetAlwaysOnTop: () => SetAlwaysOnTop, - SetBackgroundColour: () => SetBackgroundColour, - SetMaxSize: () => SetMaxSize, - SetMinSize: () => SetMinSize, - SetRelativePosition: () => SetRelativePosition, - SetResizable: () => SetResizable, - SetSize: () => SetSize, - SetTitle: () => SetTitle, - SetZoomLevel: () => SetZoomLevel, - Show: () => Show2, - Size: () => Size, - ToggleMaximise: () => ToggleMaximise, - UnMaximise: () => UnMaximise, - UnMinimise: () => UnMinimise, - Width: () => Width, - ZoomIn: () => ZoomIn, - ZoomOut: () => ZoomOut, - ZoomReset: () => ZoomReset - }); - var center = 0; - var setTitle = 1; - var fullscreen = 2; - var unFullscreen = 3; - var setSize = 4; - var size = 5; - var setMaxSize = 6; - var setMinSize = 7; - var setAlwaysOnTop = 8; - var setRelativePosition = 9; - var relativePosition = 10; - var screen = 11; - var hide = 12; - var maximise = 13; - var unMaximise = 14; - var toggleMaximise = 15; - var minimise = 16; - var unMinimise = 17; - var restore = 18; - var show = 19; - var close = 20; - var setBackgroundColour = 21; - var setResizable2 = 22; - var width = 23; - var height = 24; - var zoomIn = 25; - var zoomOut = 26; - var zoomReset = 27; - var getZoomLevel = 28; - var setZoomLevel = 29; - var thisWindow = Get(""); - function createWindow(call10) { - return { - Get: (windowName) => createWindow(newRuntimeCallerWithID(objectNames.Window, windowName)), - Center: () => call10(center), - SetTitle: (title) => call10(setTitle, { title }), - Fullscreen: () => call10(fullscreen), - UnFullscreen: () => call10(unFullscreen), - SetSize: (width2, height2) => call10(setSize, { width: width2, height: height2 }), - Size: () => call10(size), - SetMaxSize: (width2, height2) => call10(setMaxSize, { width: width2, height: height2 }), - SetMinSize: (width2, height2) => call10(setMinSize, { width: width2, height: height2 }), - SetAlwaysOnTop: (onTop) => call10(setAlwaysOnTop, { alwaysOnTop: onTop }), - SetRelativePosition: (x, y) => call10(setRelativePosition, { x, y }), - RelativePosition: () => call10(relativePosition), - Screen: () => call10(screen), - Hide: () => call10(hide), - Maximise: () => call10(maximise), - UnMaximise: () => call10(unMaximise), - ToggleMaximise: () => call10(toggleMaximise), - Minimise: () => call10(minimise), - UnMinimise: () => call10(unMinimise), - Restore: () => call10(restore), - Show: () => call10(show), - Close: () => call10(close), - SetBackgroundColour: (r, g, b, a) => call10(setBackgroundColour, { r, g, b, a }), - SetResizable: (resizable2) => call10(setResizable2, { resizable: resizable2 }), - Width: () => call10(width), - Height: () => call10(height), - ZoomIn: () => call10(zoomIn), - ZoomOut: () => call10(zoomOut), - ZoomReset: () => call10(zoomReset), - GetZoomLevel: () => call10(getZoomLevel), - SetZoomLevel: (zoomLevel) => call10(setZoomLevel, { zoomLevel }) - }; - } - function Get(windowName) { - return createWindow(newRuntimeCallerWithID(objectNames.Window, windowName)); - } - function Center() { - thisWindow.Center(); - } - function SetTitle(title) { - thisWindow.SetTitle(title); - } - function Fullscreen() { - thisWindow.Fullscreen(); - } - function SetSize(width2, height2) { - thisWindow.SetSize(width2, height2); - } - function Size() { - return thisWindow.Size(); - } - function SetMaxSize(width2, height2) { - thisWindow.SetMaxSize(width2, height2); - } - function SetMinSize(width2, height2) { - thisWindow.SetMinSize(width2, height2); - } - function SetAlwaysOnTop(onTop) { - thisWindow.SetAlwaysOnTop(onTop); - } - function SetRelativePosition(x, y) { - thisWindow.SetRelativePosition(x, y); - } - function RelativePosition() { - return thisWindow.RelativePosition(); - } - function Screen() { - return thisWindow.Screen(); - } - function Hide2() { - thisWindow.Hide(); - } - function Maximise() { - thisWindow.Maximise(); - } - function UnMaximise() { - thisWindow.UnMaximise(); - } - function ToggleMaximise() { - thisWindow.ToggleMaximise(); - } - function Minimise() { - thisWindow.Minimise(); - } - function UnMinimise() { - thisWindow.UnMinimise(); - } - function Restore() { - thisWindow.Restore(); - } - function Show2() { - thisWindow.Show(); - } - function Close() { - thisWindow.Close(); - } - function SetBackgroundColour(r, g, b, a) { - thisWindow.SetBackgroundColour(r, g, b, a); - } - function SetResizable(resizable2) { - thisWindow.SetResizable(resizable2); - } - function Width() { - return thisWindow.Width(); - } - function Height() { - return thisWindow.Height(); - } - function ZoomIn() { - thisWindow.ZoomIn(); - } - function ZoomOut() { - thisWindow.ZoomOut(); - } - function ZoomReset() { - thisWindow.ZoomReset(); - } - function GetZoomLevel() { - return thisWindow.GetZoomLevel(); - } - function SetZoomLevel(zoomLevel) { - thisWindow.SetZoomLevel(zoomLevel); - } - - // desktop/@wailsio/runtime/src/wml.js - var wml_exports = {}; - __export(wml_exports, { - Reload: () => Reload - }); - - // desktop/@wailsio/runtime/src/events.js - var events_exports = {}; - __export(events_exports, { - Emit: () => Emit, - Off: () => Off, - OffAll: () => OffAll, - On: () => On, - OnMultiple: () => OnMultiple, - Once: () => Once, - Types: () => Types, - WailsEvent: () => WailsEvent, - setup: () => setup - }); - - // desktop/@wailsio/runtime/src/event_types.js - var EventTypes = { - Windows: { - SystemThemeChanged: "windows:SystemThemeChanged", - APMPowerStatusChange: "windows:APMPowerStatusChange", - APMSuspend: "windows:APMSuspend", - APMResumeAutomatic: "windows:APMResumeAutomatic", - APMResumeSuspend: "windows:APMResumeSuspend", - APMPowerSettingChange: "windows:APMPowerSettingChange", - ApplicationStarted: "windows:ApplicationStarted", - WebViewNavigationCompleted: "windows:WebViewNavigationCompleted", - WindowInactive: "windows:WindowInactive", - WindowActive: "windows:WindowActive", - WindowClickActive: "windows:WindowClickActive", - WindowMaximise: "windows:WindowMaximise", - WindowUnMaximise: "windows:WindowUnMaximise", - WindowFullscreen: "windows:WindowFullscreen", - WindowUnFullscreen: "windows:WindowUnFullscreen", - WindowRestore: "windows:WindowRestore", - WindowMinimise: "windows:WindowMinimise", - WindowUnMinimise: "windows:WindowUnMinimise", - WindowClose: "windows:WindowClose", - WindowSetFocus: "windows:WindowSetFocus", - WindowKillFocus: "windows:WindowKillFocus", - WindowDragDrop: "windows:WindowDragDrop", - WindowDragEnter: "windows:WindowDragEnter", - WindowDragLeave: "windows:WindowDragLeave", - WindowDragOver: "windows:WindowDragOver" - }, - Mac: { - ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive", - ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties", - ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance", - ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon", - ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState", - ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters", - ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame", - ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation", - ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", - ApplicationDidHide: "mac:ApplicationDidHide", - ApplicationDidResignActiveNotification: "mac:ApplicationDidResignActiveNotification", - ApplicationDidUnhide: "mac:ApplicationDidUnhide", - ApplicationDidUpdate: "mac:ApplicationDidUpdate", - ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive", - ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching", - ApplicationWillHide: "mac:ApplicationWillHide", - ApplicationWillResignActive: "mac:ApplicationWillResignActive", - ApplicationWillTerminate: "mac:ApplicationWillTerminate", - ApplicationWillUnhide: "mac:ApplicationWillUnhide", - ApplicationWillUpdate: "mac:ApplicationWillUpdate", - ApplicationDidChangeTheme: "mac:ApplicationDidChangeTheme!", - ApplicationShouldHandleReopen: "mac:ApplicationShouldHandleReopen!", - WindowDidBecomeKey: "mac:WindowDidBecomeKey", - WindowDidBecomeMain: "mac:WindowDidBecomeMain", - WindowDidBeginSheet: "mac:WindowDidBeginSheet", - WindowDidChangeAlpha: "mac:WindowDidChangeAlpha", - WindowDidChangeBackingLocation: "mac:WindowDidChangeBackingLocation", - WindowDidChangeBackingProperties: "mac:WindowDidChangeBackingProperties", - WindowDidChangeCollectionBehavior: "mac:WindowDidChangeCollectionBehavior", - WindowDidChangeEffectiveAppearance: "mac:WindowDidChangeEffectiveAppearance", - WindowDidChangeOcclusionState: "mac:WindowDidChangeOcclusionState", - WindowDidChangeOrderingMode: "mac:WindowDidChangeOrderingMode", - WindowDidChangeScreen: "mac:WindowDidChangeScreen", - WindowDidChangeScreenParameters: "mac:WindowDidChangeScreenParameters", - WindowDidChangeScreenProfile: "mac:WindowDidChangeScreenProfile", - WindowDidChangeScreenSpace: "mac:WindowDidChangeScreenSpace", - WindowDidChangeScreenSpaceProperties: "mac:WindowDidChangeScreenSpaceProperties", - WindowDidChangeSharingType: "mac:WindowDidChangeSharingType", - WindowDidChangeSpace: "mac:WindowDidChangeSpace", - WindowDidChangeSpaceOrderingMode: "mac:WindowDidChangeSpaceOrderingMode", - WindowDidChangeTitle: "mac:WindowDidChangeTitle", - WindowDidChangeToolbar: "mac:WindowDidChangeToolbar", - WindowDidChangeVisibility: "mac:WindowDidChangeVisibility", - WindowDidDeminiaturize: "mac:WindowDidDeminiaturize", - WindowDidEndSheet: "mac:WindowDidEndSheet", - WindowDidEnterFullScreen: "mac:WindowDidEnterFullScreen", - WindowDidEnterVersionBrowser: "mac:WindowDidEnterVersionBrowser", - WindowDidExitFullScreen: "mac:WindowDidExitFullScreen", - WindowDidExitVersionBrowser: "mac:WindowDidExitVersionBrowser", - WindowDidExpose: "mac:WindowDidExpose", - WindowDidFocus: "mac:WindowDidFocus", - WindowDidMiniaturize: "mac:WindowDidMiniaturize", - WindowDidMove: "mac:WindowDidMove", - WindowDidOrderOffScreen: "mac:WindowDidOrderOffScreen", - WindowDidOrderOnScreen: "mac:WindowDidOrderOnScreen", - WindowDidResignKey: "mac:WindowDidResignKey", - WindowDidResignMain: "mac:WindowDidResignMain", - WindowDidResize: "mac:WindowDidResize", - WindowDidUpdate: "mac:WindowDidUpdate", - WindowDidUpdateAlpha: "mac:WindowDidUpdateAlpha", - WindowDidUpdateCollectionBehavior: "mac:WindowDidUpdateCollectionBehavior", - WindowDidUpdateCollectionProperties: "mac:WindowDidUpdateCollectionProperties", - WindowDidUpdateShadow: "mac:WindowDidUpdateShadow", - WindowDidUpdateTitle: "mac:WindowDidUpdateTitle", - WindowDidUpdateToolbar: "mac:WindowDidUpdateToolbar", - WindowDidUpdateVisibility: "mac:WindowDidUpdateVisibility", - WindowShouldClose: "mac:WindowShouldClose!", - WindowWillBecomeKey: "mac:WindowWillBecomeKey", - WindowWillBecomeMain: "mac:WindowWillBecomeMain", - WindowWillBeginSheet: "mac:WindowWillBeginSheet", - WindowWillChangeOrderingMode: "mac:WindowWillChangeOrderingMode", - WindowWillClose: "mac:WindowWillClose", - WindowWillDeminiaturize: "mac:WindowWillDeminiaturize", - WindowWillEnterFullScreen: "mac:WindowWillEnterFullScreen", - WindowWillEnterVersionBrowser: "mac:WindowWillEnterVersionBrowser", - WindowWillExitFullScreen: "mac:WindowWillExitFullScreen", - WindowWillExitVersionBrowser: "mac:WindowWillExitVersionBrowser", - WindowWillFocus: "mac:WindowWillFocus", - WindowWillMiniaturize: "mac:WindowWillMiniaturize", - WindowWillMove: "mac:WindowWillMove", - WindowWillOrderOffScreen: "mac:WindowWillOrderOffScreen", - WindowWillOrderOnScreen: "mac:WindowWillOrderOnScreen", - WindowWillResignMain: "mac:WindowWillResignMain", - WindowWillResize: "mac:WindowWillResize", - WindowWillUnfocus: "mac:WindowWillUnfocus", - WindowWillUpdate: "mac:WindowWillUpdate", - WindowWillUpdateAlpha: "mac:WindowWillUpdateAlpha", - WindowWillUpdateCollectionBehavior: "mac:WindowWillUpdateCollectionBehavior", - WindowWillUpdateCollectionProperties: "mac:WindowWillUpdateCollectionProperties", - WindowWillUpdateShadow: "mac:WindowWillUpdateShadow", - WindowWillUpdateTitle: "mac:WindowWillUpdateTitle", - WindowWillUpdateToolbar: "mac:WindowWillUpdateToolbar", - WindowWillUpdateVisibility: "mac:WindowWillUpdateVisibility", - WindowWillUseStandardFrame: "mac:WindowWillUseStandardFrame", - MenuWillOpen: "mac:MenuWillOpen", - MenuDidOpen: "mac:MenuDidOpen", - MenuDidClose: "mac:MenuDidClose", - MenuWillSendAction: "mac:MenuWillSendAction", - MenuDidSendAction: "mac:MenuDidSendAction", - MenuWillHighlightItem: "mac:MenuWillHighlightItem", - MenuDidHighlightItem: "mac:MenuDidHighlightItem", - MenuWillDisplayItem: "mac:MenuWillDisplayItem", - MenuDidDisplayItem: "mac:MenuDidDisplayItem", - MenuWillAddItem: "mac:MenuWillAddItem", - MenuDidAddItem: "mac:MenuDidAddItem", - MenuWillRemoveItem: "mac:MenuWillRemoveItem", - MenuDidRemoveItem: "mac:MenuDidRemoveItem", - MenuWillBeginTracking: "mac:MenuWillBeginTracking", - MenuDidBeginTracking: "mac:MenuDidBeginTracking", - MenuWillEndTracking: "mac:MenuWillEndTracking", - MenuDidEndTracking: "mac:MenuDidEndTracking", - MenuWillUpdate: "mac:MenuWillUpdate", - MenuDidUpdate: "mac:MenuDidUpdate", - MenuWillPopUp: "mac:MenuWillPopUp", - MenuDidPopUp: "mac:MenuDidPopUp", - MenuWillSendActionToItem: "mac:MenuWillSendActionToItem", - MenuDidSendActionToItem: "mac:MenuDidSendActionToItem", - WebViewDidStartProvisionalNavigation: "mac:WebViewDidStartProvisionalNavigation", - WebViewDidReceiveServerRedirectForProvisionalNavigation: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation", - WebViewDidFinishNavigation: "mac:WebViewDidFinishNavigation", - WebViewDidCommitNavigation: "mac:WebViewDidCommitNavigation", - WindowFileDraggingEntered: "mac:WindowFileDraggingEntered", - WindowFileDraggingPerformed: "mac:WindowFileDraggingPerformed", - WindowFileDraggingExited: "mac:WindowFileDraggingExited" - }, - Linux: { - SystemThemeChanged: "linux:SystemThemeChanged", - WindowLoadChanged: "linux:WindowLoadChanged", - WindowDeleteEvent: "linux:WindowDeleteEvent", - WindowFocusIn: "linux:WindowFocusIn", - WindowFocusOut: "linux:WindowFocusOut", - ApplicationStartup: "linux:ApplicationStartup" - }, - Common: { - ApplicationStarted: "common:ApplicationStarted", - WindowMaximise: "common:WindowMaximise", - WindowUnMaximise: "common:WindowUnMaximise", - WindowFullscreen: "common:WindowFullscreen", - WindowUnFullscreen: "common:WindowUnFullscreen", - WindowRestore: "common:WindowRestore", - WindowMinimise: "common:WindowMinimise", - WindowUnMinimise: "common:WindowUnMinimise", - WindowClosing: "common:WindowClosing", - WindowZoom: "common:WindowZoom", - WindowZoomIn: "common:WindowZoomIn", - WindowZoomOut: "common:WindowZoomOut", - WindowZoomReset: "common:WindowZoomReset", - WindowFocus: "common:WindowFocus", - WindowLostFocus: "common:WindowLostFocus", - WindowShow: "common:WindowShow", - WindowHide: "common:WindowHide", - WindowDPIChanged: "common:WindowDPIChanged", - WindowFilesDropped: "common:WindowFilesDropped", - WindowRuntimeReady: "common:WindowRuntimeReady", - ThemeChanged: "common:ThemeChanged" - } - }; - - // desktop/@wailsio/runtime/src/events.js - var Types = EventTypes; - window._wails = window._wails || {}; - window._wails.dispatchWailsEvent = dispatchWailsEvent; - var call7 = newRuntimeCallerWithID(objectNames.Events, ""); - var EmitMethod = 0; - var eventListeners = /* @__PURE__ */ new Map(); - var Listener = class { - constructor(eventName, callback, maxCallbacks) { - this.eventName = eventName; - this.maxCallbacks = maxCallbacks || -1; - this.Callback = (data) => { - callback(data); - if (this.maxCallbacks === -1) - return false; - this.maxCallbacks -= 1; - return this.maxCallbacks === 0; - }; - } - }; - var WailsEvent = class { - constructor(name, data = null) { - this.name = name; - this.data = data; - } - }; - function setup() { - } - function dispatchWailsEvent(event) { - let listeners = eventListeners.get(event.name); - if (listeners) { - let toRemove = listeners.filter((listener) => { - let remove = listener.Callback(event); - if (remove) - return true; - }); - if (toRemove.length > 0) { - listeners = listeners.filter((l) => !toRemove.includes(l)); - if (listeners.length === 0) - eventListeners.delete(event.name); - else - eventListeners.set(event.name, listeners); - } - } - } - function OnMultiple(eventName, callback, maxCallbacks) { - let listeners = eventListeners.get(eventName) || []; - const thisListener = new Listener(eventName, callback, maxCallbacks); - listeners.push(thisListener); - eventListeners.set(eventName, listeners); - return () => listenerOff(thisListener); - } - function On(eventName, callback) { - return OnMultiple(eventName, callback, -1); - } - function Once(eventName, callback) { - return OnMultiple(eventName, callback, 1); - } - function listenerOff(listener) { - const eventName = listener.eventName; - let listeners = eventListeners.get(eventName).filter((l) => l !== listener); - if (listeners.length === 0) - eventListeners.delete(eventName); - else - eventListeners.set(eventName, listeners); - } - function Off(eventName, ...additionalEventNames) { - let eventsToRemove = [eventName, ...additionalEventNames]; - eventsToRemove.forEach((eventName2) => eventListeners.delete(eventName2)); - } - function OffAll() { - eventListeners.clear(); - } - function Emit(event) { - return call7(EmitMethod, event); - } - - // desktop/@wailsio/runtime/src/dialogs.js - var dialogs_exports = {}; - __export(dialogs_exports, { - Error: () => Error2, - Info: () => Info, - OpenFile: () => OpenFile, - Question: () => Question, - SaveFile: () => SaveFile, - Warning: () => Warning - }); - window._wails = window._wails || {}; - window._wails.dialogErrorCallback = dialogErrorCallback; - window._wails.dialogResultCallback = dialogResultCallback; - var DialogInfo = 0; - var DialogWarning = 1; - var DialogError = 2; - var DialogQuestion = 3; - var DialogOpenFile = 4; - var DialogSaveFile = 5; - var call8 = newRuntimeCallerWithID(objectNames.Dialog, ""); - var dialogResponses = /* @__PURE__ */ new Map(); - function generateID() { - let result; - do { - result = nanoid(); - } while (dialogResponses.has(result)); - return result; - } - function dialog(type, options = {}) { - const id = generateID(); - options["dialog-id"] = id; - return new Promise((resolve, reject) => { - dialogResponses.set(id, { resolve, reject }); - call8(type, options).catch((error) => { - reject(error); - dialogResponses.delete(id); - }); - }); - } - function dialogResultCallback(id, data, isJSON) { - let p = dialogResponses.get(id); - if (p) { - if (isJSON) { - p.resolve(JSON.parse(data)); - } else { - p.resolve(data); - } - dialogResponses.delete(id); - } - } - function dialogErrorCallback(id, message) { - let p = dialogResponses.get(id); - if (p) { - p.reject(message); - dialogResponses.delete(id); - } - } - var Info = (options) => dialog(DialogInfo, options); - var Warning = (options) => dialog(DialogWarning, options); - var Error2 = (options) => dialog(DialogError, options); - var Question = (options) => dialog(DialogQuestion, options); - var OpenFile = (options) => dialog(DialogOpenFile, options); - var SaveFile = (options) => dialog(DialogSaveFile, options); - - // desktop/@wailsio/runtime/src/wml.js - function sendEvent(eventName, data = null) { - let event = new WailsEvent(eventName, data); - Emit(event); - } - function addWMLEventListeners() { - const elements = document.querySelectorAll("[wml-event]"); - elements.forEach(function(element) { - const eventType = element.getAttribute("wml-event"); - const confirm = element.getAttribute("wml-confirm"); - const trigger = element.getAttribute("wml-trigger") || "click"; - let callback = function() { - if (confirm) { - Question({ Title: "Confirm", Message: confirm, Detached: false, Buttons: [{ Label: "Yes" }, { Label: "No", IsDefault: true }] }).then(function(result) { - if (result !== "No") { - sendEvent(eventType); - } - }); - return; - } - sendEvent(eventType); - }; - element.removeEventListener(trigger, callback); - element.addEventListener(trigger, callback); - }); - } - function callWindowMethod(windowName, method) { - let targetWindow = Get(windowName); - let methodMap = WindowMethods(targetWindow); - if (!methodMap.has(method)) { - console.log("Window method " + method + " not found"); - } - try { - methodMap.get(method)(); - } catch (e) { - console.error("Error calling window method '" + method + "': " + e); - } - } - function addWMLWindowListeners() { - const elements = document.querySelectorAll("[wml-window]"); - elements.forEach(function(element) { - const windowMethod = element.getAttribute("wml-window"); - const confirm = element.getAttribute("wml-confirm"); - const trigger = element.getAttribute("wml-trigger") || "click"; - const targetWindow = element.getAttribute("wml-target-window") || ""; - let callback = function() { - if (confirm) { - Question({ Title: "Confirm", Message: confirm, Buttons: [{ Label: "Yes" }, { Label: "No", IsDefault: true }] }).then(function(result) { - if (result !== "No") { - callWindowMethod(targetWindow, windowMethod); - } - }); - return; - } - callWindowMethod(targetWindow, windowMethod); - }; - element.removeEventListener(trigger, callback); - element.addEventListener(trigger, callback); - }); - } - function addWMLOpenBrowserListener() { - const elements = document.querySelectorAll("[wml-openurl]"); - elements.forEach(function(element) { - const url = element.getAttribute("wml-openurl"); - const confirm = element.getAttribute("wml-confirm"); - const trigger = element.getAttribute("wml-trigger") || "click"; - let callback = function() { - if (confirm) { - Question({ Title: "Confirm", Message: confirm, Buttons: [{ Label: "Yes" }, { Label: "No", IsDefault: true }] }).then(function(result) { - if (result !== "No") { - void OpenURL(url); - } - }); - return; - } - void OpenURL(url); - }; - element.removeEventListener(trigger, callback); - element.addEventListener(trigger, callback); - }); - } - function Reload() { - addWMLEventListeners(); - addWMLWindowListeners(); - addWMLOpenBrowserListener(); - } - function WindowMethods(targetWindow) { - let result = /* @__PURE__ */ new Map(); - for (let method in targetWindow) { - if (typeof targetWindow[method] === "function") { - result.set(method, targetWindow[method]); - } - } - return result; - } - - // desktop/@wailsio/runtime/src/calls.js - var calls_exports = {}; - __export(calls_exports, { - ByID: () => ByID, - ByName: () => ByName, - Call: () => Call, - Plugin: () => Plugin - }); - window._wails = window._wails || {}; - window._wails.callResultHandler = resultHandler; - window._wails.callErrorHandler = errorHandler; - var CallBinding = 0; - var call9 = newRuntimeCallerWithID(objectNames.Call, ""); - var cancelCall = newRuntimeCallerWithID(objectNames.CancelCall, ""); - var callResponses = /* @__PURE__ */ new Map(); - function generateID2() { - let result; - do { - result = nanoid(); - } while (callResponses.has(result)); - return result; - } - function resultHandler(id, data, isJSON) { - const promiseHandler = getAndDeleteResponse(id); - if (promiseHandler) { - promiseHandler.resolve(isJSON ? JSON.parse(data) : data); - } - } - function errorHandler(id, message) { - const promiseHandler = getAndDeleteResponse(id); - if (promiseHandler) { - promiseHandler.reject(message); - } - } - function getAndDeleteResponse(id) { - const response = callResponses.get(id); - callResponses.delete(id); - return response; - } - function callBinding(type, options = {}) { - const id = generateID2(); - const doCancel = () => { - cancelCall(type, { "call-id": id }); - }; - var queuedCancel = false, callRunning = false; - var p = new Promise((resolve, reject) => { - options["call-id"] = id; - callResponses.set(id, { resolve, reject }); - call9(type, options).then((_) => { - callRunning = true; - if (queuedCancel) { - doCancel(); - } - }).catch((error) => { - reject(error); - callResponses.delete(id); - }); - }); - p.cancel = () => { - if (callRunning) { - doCancel(); - } else { - queuedCancel = true; - } - }; - return p; - } - function Call(options) { - return callBinding(CallBinding, options); - } - function ByName(name, ...args) { - if (typeof name !== "string" || name.split(".").length !== 3) { - throw new Error("CallByName requires a string in the format 'package.struct.method'"); - } - let [packageName, structName, methodName] = name.split("."); - return callBinding(CallBinding, { - packageName, - structName, - methodName, - args - }); - } - function ByID(methodID, ...args) { - return callBinding(CallBinding, { - methodID, - args - }); - } - function Plugin(pluginName, methodName, ...args) { - return callBinding(CallBinding, { - packageName: "wails-plugins", - structName: pluginName, - methodName, - args - }); - } - - // desktop/compiled/main.js - window._wails = window._wails || {}; - window._wails.invoke = invoke; - window.wails = window.wails || {}; - window.wails.Application = application_exports; - window.wails.Browser = browser_exports; - window.wails.Call = calls_exports; - window.wails.Clipboard = clipboard_exports; - window.wails.Dialogs = dialogs_exports; - window.wails.Events = events_exports; - window.wails.Flags = flags_exports; - window.wails.Screens = screens_exports; - window.wails.System = system_exports; - window.wails.Window = window_exports; - window.wails.WML = wml_exports; - var isReady = false; - document.addEventListener("DOMContentLoaded", function() { - isReady = true; - window._wails.invoke("wails:runtime:ready"); - if (true) { - debugLog("Wails Runtime Loaded"); - } - }); - function whenReady(fn) { - if (isReady || document.readyState === "complete") { - fn(); - } else { - document.addEventListener("DOMContentLoaded", fn); - } - } - whenReady(() => { - Reload(); - }); -})(); -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvYXBwbGljYXRpb24uanMiLCAiLi4vLi4vLi4vcnVudGltZS9ub2RlX21vZHVsZXMvbmFub2lkL25vbi1zZWN1cmUvaW5kZXguanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3J1bnRpbWUuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXIuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZC5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvc3lzdGVtLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jb250ZXh0bWVudS5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3MuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RyYWcuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3NjcmVlbnMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dpbmRvdy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvd21sLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9ldmVudHMuanMiLCAiLi4vLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50X3R5cGVzLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9kaWFsb2dzLmpzIiwgIi4uLy4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxscy5qcyIsICIuLi8uLi8uLi9ydW50aW1lL2Rlc2t0b3AvY29tcGlsZWQvbWFpbi5qcyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBMb2dzIGEgbWVzc2FnZSB0byB0aGUgY29uc29sZSB3aXRoIGN1c3RvbSBmb3JtYXR0aW5nLlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBUaGUgbWVzc2FnZSB0byBiZSBsb2dnZWQuXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVidWdMb2cobWVzc2FnZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAnJWMgd2FpbHMzICVjICcgKyBtZXNzYWdlICsgJyAnLFxuICAgICAgICAnYmFja2dyb3VuZDogI2FhMDAwMDsgY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDNweCAwcHggMHB4IDNweDsgcGFkZGluZzogMXB4OyBmb250LXNpemU6IDAuN3JlbScsXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjMDA5OTAwOyBjb2xvcjogI2ZmZjsgYm9yZGVyLXJhZGl1czogMHB4IDNweCAzcHggMHB4OyBwYWRkaW5nOiAxcHg7IGZvbnQtc2l6ZTogMC43cmVtJ1xuICAgICk7XG59IiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZVwiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQXBwbGljYXRpb24sICcnKTtcblxuY29uc3QgSGlkZU1ldGhvZCA9IDA7XG5jb25zdCBTaG93TWV0aG9kID0gMTtcbmNvbnN0IFF1aXRNZXRob2QgPSAyO1xuXG4vKipcbiAqIEhpZGVzIGEgY2VydGFpbiBtZXRob2QgYnkgY2FsbGluZyB0aGUgSGlkZU1ldGhvZCBmdW5jdGlvbi5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XG4gICAgcmV0dXJuIGNhbGwoSGlkZU1ldGhvZCk7XG59XG5cbi8qKlxuICogQ2FsbHMgdGhlIFNob3dNZXRob2QgYW5kIHJldHVybnMgdGhlIHJlc3VsdC5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fVxuICovXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpIHtcbiAgICByZXR1cm4gY2FsbChTaG93TWV0aG9kKTtcbn1cblxuLyoqXG4gKiBDYWxscyB0aGUgUXVpdE1ldGhvZCB0byB0ZXJtaW5hdGUgdGhlIHByb2dyYW0uXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFF1aXQoKSB7XG4gICAgcmV0dXJuIGNhbGwoUXVpdE1ldGhvZCk7XG59XG4iLCAibGV0IHVybEFscGhhYmV0ID1cbiAgJ3VzZWFuZG9tLTI2VDE5ODM0MFBYNzVweEpBQ0tWRVJZTUlOREJVU0hXT0xGX0dRWmJmZ2hqa2xxdnd5enJpY3QnXG5leHBvcnQgbGV0IGN1c3RvbUFscGhhYmV0ID0gKGFscGhhYmV0LCBkZWZhdWx0U2l6ZSA9IDIxKSA9PiB7XG4gIHJldHVybiAoc2l6ZSA9IGRlZmF1bHRTaXplKSA9PiB7XG4gICAgbGV0IGlkID0gJydcbiAgICBsZXQgaSA9IHNpemVcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICBpZCArPSBhbHBoYWJldFsoTWF0aC5yYW5kb20oKSAqIGFscGhhYmV0Lmxlbmd0aCkgfCAwXVxuICAgIH1cbiAgICByZXR1cm4gaWRcbiAgfVxufVxuZXhwb3J0IGxldCBuYW5vaWQgPSAoc2l6ZSA9IDIxKSA9PiB7XG4gIGxldCBpZCA9ICcnXG4gIGxldCBpID0gc2l6ZVxuICB3aGlsZSAoaS0tKSB7XG4gICAgaWQgKz0gdXJsQWxwaGFiZXRbKE1hdGgucmFuZG9tKCkgKiA2NCkgfCAwXVxuICB9XG4gIHJldHVybiBpZFxufVxuIiwgIi8qXG4gXyAgICAgX18gICAgIF8gX19cbnwgfCAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQgeyBuYW5vaWQgfSBmcm9tICduYW5vaWQvbm9uLXNlY3VyZSc7XG5cbmNvbnN0IHJ1bnRpbWVVUkwgPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luICsgXCIvd2FpbHMvcnVudGltZVwiO1xuXG4vLyBPYmplY3QgTmFtZXNcbmV4cG9ydCBjb25zdCBvYmplY3ROYW1lcyA9IHtcbiAgICBDYWxsOiAwLFxuICAgIENsaXBib2FyZDogMSxcbiAgICBBcHBsaWNhdGlvbjogMixcbiAgICBFdmVudHM6IDMsXG4gICAgQ29udGV4dE1lbnU6IDQsXG4gICAgRGlhbG9nOiA1LFxuICAgIFdpbmRvdzogNixcbiAgICBTY3JlZW5zOiA3LFxuICAgIFN5c3RlbTogOCxcbiAgICBCcm93c2VyOiA5LFxufVxuZXhwb3J0IGxldCBjbGllbnRJZCA9IG5hbm9pZCgpO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBydW50aW1lIGNhbGxlciBmdW5jdGlvbiB0aGF0IGludm9rZXMgYSBzcGVjaWZpZWQgbWV0aG9kIG9uIGEgZ2l2ZW4gb2JqZWN0IHdpdGhpbiBhIHNwZWNpZmllZCB3aW5kb3cgY29udGV4dC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IC0gVGhlIG9iamVjdCBvbiB3aGljaCB0aGUgbWV0aG9kIGlzIHRvIGJlIGludm9rZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgY29udGV4dCBpbiB3aGljaCB0aGUgbWV0aG9kIHNob3VsZCBiZSBjYWxsZWQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IEEgcnVudGltZSBjYWxsZXIgZnVuY3Rpb24gdGhhdCB0YWtlcyB0aGUgbWV0aG9kIG5hbWUgYW5kIG9wdGlvbmFsbHkgYXJndW1lbnRzIGFuZCBpbnZva2VzIHRoZSBtZXRob2Qgd2l0aGluIHRoZSBzcGVjaWZpZWQgd2luZG93IGNvbnRleHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdCwgd2luZG93TmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAobWV0aG9kLCBhcmdzPW51bGwpIHtcbiAgICAgICAgcmV0dXJuIHJ1bnRpbWVDYWxsKG9iamVjdCArIFwiLlwiICsgbWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKTtcbiAgICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcnVudGltZSBjYWxsZXIgd2l0aCBzcGVjaWZpZWQgSUQuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3QgdG8gaW52b2tlIHRoZSBtZXRob2Qgb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cuXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn0gLSBUaGUgbmV3IHJ1bnRpbWUgY2FsbGVyIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3QsIHdpbmRvd05hbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKG1ldGhvZCwgYXJncz1udWxsKSB7XG4gICAgICAgIHJldHVybiBydW50aW1lQ2FsbFdpdGhJRChvYmplY3QsIG1ldGhvZCwgd2luZG93TmFtZSwgYXJncyk7XG4gICAgfTtcbn1cblxuXG5mdW5jdGlvbiBydW50aW1lQ2FsbChtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcbiAgICBpZiggbWV0aG9kICkge1xuICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcIm1ldGhvZFwiLCBtZXRob2QpO1xuICAgIH1cbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICB9O1xuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuICAgIGlmIChhcmdzKSB7XG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiYXJnc1wiLCBKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgfVxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGZldGNoKHVybCwgZmV0Y2hPcHRpb25zKVxuICAgICAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgICAgICAgICAvLyBjaGVjayBjb250ZW50IHR5cGVcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpICYmIHJlc3BvbnNlLmhlYWRlcnMuZ2V0KFwiQ29udGVudC1UeXBlXCIpLmluZGV4T2YoXCJhcHBsaWNhdGlvbi9qc29uXCIpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVqZWN0KEVycm9yKHJlc3BvbnNlLnN0YXR1c1RleHQpKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAudGhlbihkYXRhID0+IHJlc29sdmUoZGF0YSkpXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4gcmVqZWN0KGVycm9yKSk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHJ1bnRpbWVDYWxsV2l0aElEKG9iamVjdElELCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpIHtcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcbiAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChcIm9iamVjdFwiLCBvYmplY3RJRCk7XG4gICAgdXJsLnNlYXJjaFBhcmFtcy5hcHBlbmQoXCJtZXRob2RcIiwgbWV0aG9kKTtcbiAgICBsZXQgZmV0Y2hPcHRpb25zID0ge1xuICAgICAgICBoZWFkZXJzOiB7fSxcbiAgICB9O1xuICAgIGlmICh3aW5kb3dOYW1lKSB7XG4gICAgICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuICAgIGlmIChhcmdzKSB7XG4gICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKFwiYXJnc1wiLCBKU09OLnN0cmluZ2lmeShhcmdzKSk7XG4gICAgfVxuICAgIGZldGNoT3B0aW9ucy5oZWFkZXJzW1wieC13YWlscy1jbGllbnQtaWRcIl0gPSBjbGllbnRJZDtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBmZXRjaCh1cmwsIGZldGNoT3B0aW9ucylcbiAgICAgICAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2Uub2spIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY2hlY2sgY29udGVudCB0eXBlXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKSAmJiByZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKS5pbmRleE9mKFwiYXBwbGljYXRpb24vanNvblwiKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlamVjdChFcnJvcihyZXNwb25zZS5zdGF0dXNUZXh0KSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnRoZW4oZGF0YSA9PiByZXNvbHZlKGRhdGEpKVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHJlamVjdChlcnJvcikpO1xuICAgIH0pO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkJyb3dzZXIsICcnKTtcbmNvbnN0IEJyb3dzZXJPcGVuVVJMID0gMDtcblxuLyoqXG4gKiBPcGVuIGEgYnJvd3NlciB3aW5kb3cgdG8gdGhlIGdpdmVuIFVSTFxuICogQHBhcmFtIHtzdHJpbmd9IHVybCAtIFRoZSBVUkwgdG8gb3BlblxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9wZW5VUkwodXJsKSB7XG4gICAgcmV0dXJuIGNhbGwoQnJvd3Nlck9wZW5VUkwsIHt1cmx9KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyV2l0aElEKG9iamVjdE5hbWVzLkNsaXBib2FyZCwgJycpO1xuY29uc3QgQ2xpcGJvYXJkU2V0VGV4dCA9IDA7XG5jb25zdCBDbGlwYm9hcmRUZXh0ID0gMTtcblxuLyoqXG4gKiBTZXRzIHRoZSB0ZXh0IHRvIHRoZSBDbGlwYm9hcmQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSBUaGUgdGV4dCB0byBiZSBzZXQgdG8gdGhlIENsaXBib2FyZC5cbiAqIEByZXR1cm4ge1Byb21pc2V9IC0gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIHN1Y2Nlc3NmdWwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRUZXh0KHRleHQpIHtcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRTZXRUZXh0LCB7dGV4dH0pO1xufVxuXG4vKipcbiAqIEdldCB0aGUgQ2xpcGJvYXJkIHRleHRcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHRleHQgZnJvbSB0aGUgQ2xpcGJvYXJkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gVGV4dCgpIHtcbiAgICByZXR1cm4gY2FsbChDbGlwYm9hcmRUZXh0KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5sZXQgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU3lzdGVtLCAnJyk7XG5jb25zdCBzeXN0ZW1Jc0RhcmtNb2RlID0gMDtcbmNvbnN0IGVudmlyb25tZW50ID0gMTtcblxuZXhwb3J0IGZ1bmN0aW9uIGludm9rZShtc2cpIHtcbiAgICBpZih3aW5kb3cuY2hyb21lKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuY2hyb21lLndlYnZpZXcucG9zdE1lc3NhZ2UobXNnKTtcbiAgICB9XG4gICAgcmV0dXJuIHdpbmRvdy53ZWJraXQubWVzc2FnZUhhbmRsZXJzLmV4dGVybmFsLnBvc3RNZXNzYWdlKG1zZyk7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBSZXRyaWV2ZXMgdGhlIHN5c3RlbSBkYXJrIG1vZGUgc3RhdHVzLlxuICogQHJldHVybnMge1Byb21pc2U8Ym9vbGVhbj59IC0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBib29sZWFuIHZhbHVlIGluZGljYXRpbmcgaWYgdGhlIHN5c3RlbSBpcyBpbiBkYXJrIG1vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0RhcmtNb2RlKCkge1xuICAgIHJldHVybiBjYWxsKHN5c3RlbUlzRGFya01vZGUpO1xufVxuXG4vKipcbiAqIEZldGNoZXMgdGhlIGNhcGFiaWxpdGllcyBvZiB0aGUgYXBwbGljYXRpb24gZnJvbSB0aGUgc2VydmVyLlxuICpcbiAqIEBhc3luY1xuICogQGZ1bmN0aW9uIENhcGFiaWxpdGllc1xuICogQHJldHVybnMge1Byb21pc2U8T2JqZWN0Pn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGNhcGFiaWxpdGllcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhcGFiaWxpdGllcygpIHtcbiAgICBsZXQgcmVzcG9uc2UgPSBmZXRjaChcIi93YWlscy9jYXBhYmlsaXRpZXNcIik7XG4gICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbn1cblxuLyoqXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBFbnZpcm9ubWVudEluZm9cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBPUyAtIFRoZSBvcGVyYXRpbmcgc3lzdGVtIGluIHVzZS5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBBcmNoIC0gVGhlIGFyY2hpdGVjdHVyZSBvZiB0aGUgc3lzdGVtLlxuICovXG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBSZXRyaWV2ZXMgZW52aXJvbm1lbnQgZGV0YWlscy5cbiAqIEByZXR1cm5zIHtQcm9taXNlPEVudmlyb25tZW50SW5mbz59IC0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gb2JqZWN0IGNvbnRhaW5pbmcgT1MgYW5kIHN5c3RlbSBhcmNoaXRlY3R1cmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBFbnZpcm9ubWVudCgpIHtcbiAgICByZXR1cm4gY2FsbChlbnZpcm9ubWVudCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cy5cbiAqXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBvcGVyYXRpbmcgc3lzdGVtIGlzIFdpbmRvd3MsIG90aGVyd2lzZSBmYWxzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzV2luZG93cygpIHtcbiAgICByZXR1cm4gd2luZG93Ll93YWlscy5lbnZpcm9ubWVudC5PUyA9PT0gXCJ3aW5kb3dzXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgTGludXguXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgdHJ1ZSBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIExpbnV4LCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0xpbnV4KCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcImxpbnV4XCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGlzIGEgbWFjT1Mgb3BlcmF0aW5nIHN5c3RlbS5cbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgZW52aXJvbm1lbnQgaXMgbWFjT1MsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzTWFjKCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50Lk9TID09PSBcImRhcndpblwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQU1ENjQoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuQXJjaCA9PT0gXCJhbWQ2NFwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBhcmNoaXRlY3R1cmUgaXMgQVJNLlxuICpcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBjdXJyZW50IGFyY2hpdGVjdHVyZSBpcyBBUk0sIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQVJNKCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZS5cbiAqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBSZXR1cm5zIHRydWUgaWYgdGhlIGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZSwgb3RoZXJ3aXNlIHJldHVybnMgZmFsc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0FSTTY0KCkge1xuICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmVudmlyb25tZW50LkFyY2ggPT09IFwiYXJtNjRcIjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIElzRGVidWcoKSB7XG4gICAgcmV0dXJuIHdpbmRvdy5fd2FpbHMuZW52aXJvbm1lbnQuRGVidWcgPT09IHRydWU7XG59XG5cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXJXaXRoSUQsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lXCI7XG5pbXBvcnQge0lzRGVidWd9IGZyb20gXCIuL3N5c3RlbVwiO1xuXG4vLyBzZXR1cFxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51JywgY29udGV4dE1lbnVIYW5kbGVyKTtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ29udGV4dE1lbnUsICcnKTtcbmNvbnN0IENvbnRleHRNZW51T3BlbiA9IDA7XG5cbmZ1bmN0aW9uIG9wZW5Db250ZXh0TWVudShpZCwgeCwgeSwgZGF0YSkge1xuICAgIHZvaWQgY2FsbChDb250ZXh0TWVudU9wZW4sIHtpZCwgeCwgeSwgZGF0YX0pO1xufVxuXG5mdW5jdGlvbiBjb250ZXh0TWVudUhhbmRsZXIoZXZlbnQpIHtcbiAgICAvLyBDaGVjayBmb3IgY3VzdG9tIGNvbnRleHQgbWVudVxuICAgIGxldCBlbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgIGxldCBjdXN0b21Db250ZXh0TWVudSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoXCItLWN1c3RvbS1jb250ZXh0bWVudVwiKTtcbiAgICBjdXN0b21Db250ZXh0TWVudSA9IGN1c3RvbUNvbnRleHRNZW51ID8gY3VzdG9tQ29udGV4dE1lbnUudHJpbSgpIDogXCJcIjtcbiAgICBpZiAoY3VzdG9tQ29udGV4dE1lbnUpIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgbGV0IGN1c3RvbUNvbnRleHRNZW51RGF0YSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoXCItLWN1c3RvbS1jb250ZXh0bWVudS1kYXRhXCIpO1xuICAgICAgICBvcGVuQ29udGV4dE1lbnUoY3VzdG9tQ29udGV4dE1lbnUsIGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFksIGN1c3RvbUNvbnRleHRNZW51RGF0YSk7XG4gICAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpO1xufVxuXG5cbi8qXG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IGF1dG87IChkZWZhdWx0KSB3aWxsIHNob3cgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51IGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlIE9SIHRleHQgaGFzIGJlZW4gc2VsZWN0ZWQgT1IgZWxlbWVudCBpcyBpbnB1dCBvciB0ZXh0YXJlYVxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBzaG93OyB3aWxsIGFsd2F5cyBzaG93IHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBoaWRlOyB3aWxsIGFsd2F5cyBoaWRlIHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuXG5UaGlzIHJ1bGUgaXMgaW5oZXJpdGVkIGxpa2Ugbm9ybWFsIENTUyBydWxlcywgc28gbmVzdGluZyB3b3JrcyBhcyBleHBlY3RlZFxuKi9cbmZ1bmN0aW9uIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpIHtcblxuICAgIC8vIERlYnVnIGJ1aWxkcyBhbHdheXMgc2hvdyB0aGUgbWVudVxuICAgIGlmIChJc0RlYnVnKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFByb2Nlc3MgZGVmYXVsdCBjb250ZXh0IG1lbnVcbiAgICBjb25zdCBlbGVtZW50ID0gZXZlbnQudGFyZ2V0O1xuICAgIGNvbnN0IGNvbXB1dGVkU3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KTtcbiAgICBjb25zdCBkZWZhdWx0Q29udGV4dE1lbnVBY3Rpb24gPSBjb21wdXRlZFN0eWxlLmdldFByb3BlcnR5VmFsdWUoXCItLWRlZmF1bHQtY29udGV4dG1lbnVcIikudHJpbSgpO1xuICAgIHN3aXRjaCAoZGVmYXVsdENvbnRleHRNZW51QWN0aW9uKSB7XG4gICAgICAgIGNhc2UgXCJzaG93XCI6XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGNhc2UgXCJoaWRlXCI6XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgY29udGVudEVkaXRhYmxlIGlzIHRydWVcbiAgICAgICAgICAgIGlmIChlbGVtZW50LmlzQ29udGVudEVkaXRhYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0ZXh0IGhhcyBiZWVuIHNlbGVjdGVkXG4gICAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICAgICAgICBjb25zdCBoYXNTZWxlY3Rpb24gPSAoc2VsZWN0aW9uLnRvU3RyaW5nKCkubGVuZ3RoID4gMClcbiAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNlbGVjdGlvbi5yYW5nZUNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdChpKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVjdHMgPSByYW5nZS5nZXRDbGllbnRSZWN0cygpO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHJlY3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0ID0gcmVjdHNbal07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludChyZWN0LmxlZnQsIHJlY3QudG9wKSA9PT0gZWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRhZ25hbWUgaXMgaW5wdXQgb3IgdGV4dGFyZWFcbiAgICAgICAgICAgIGlmIChlbGVtZW50LnRhZ05hbWUgPT09IFwiSU5QVVRcIiB8fCBlbGVtZW50LnRhZ05hbWUgPT09IFwiVEVYVEFSRUFcIikge1xuICAgICAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24gfHwgKCFlbGVtZW50LnJlYWRPbmx5ICYmICFlbGVtZW50LmRpc2FibGVkKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBoaWRlIGRlZmF1bHQgY29udGV4dCBtZW51XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIFJldHJpZXZlcyB0aGUgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIHRoZSBzcGVjaWZpZWQga2V5IGZyb20gdGhlIGZsYWcgbWFwLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXlTdHJpbmcgLSBUaGUga2V5IHRvIHJldHJpZXZlIHRoZSB2YWx1ZSBmb3IuXG4gKiBAcmV0dXJuIHsqfSAtIFRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBrZXkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRGbGFnKGtleVN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmZsYWdzW2tleVN0cmluZ107XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gcmV0cmlldmUgZmxhZyAnXCIgKyBrZXlTdHJpbmcgKyBcIic6IFwiICsgZSk7XG4gICAgfVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbmltcG9ydCB7aW52b2tlLCBJc1dpbmRvd3N9IGZyb20gXCIuL3N5c3RlbVwiO1xuaW1wb3J0IHtHZXRGbGFnfSBmcm9tIFwiLi9mbGFnc1wiO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLnNldFJlc2l6YWJsZSA9IHNldFJlc2l6YWJsZTtcbndpbmRvdy5fd2FpbHMuZW5kRHJhZyA9IGVuZERyYWc7XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgb25Nb3VzZURvd24pO1xud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG9uTW91c2VNb3ZlKTtcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25Nb3VzZVVwKTtcblxuXG5sZXQgc2hvdWxkRHJhZyA9IGZhbHNlO1xubGV0IHJlc2l6ZUVkZ2UgPSBudWxsO1xubGV0IHJlc2l6YWJsZSA9IGZhbHNlO1xubGV0IGRlZmF1bHRDdXJzb3IgPSBcImF1dG9cIjtcblxuZnVuY3Rpb24gZHJhZ1Rlc3QoZSkge1xuICAgIGxldCB2YWwgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlLnRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZShcIi0td2Via2l0LWFwcC1yZWdpb25cIik7XG4gICAgaWYgKCF2YWwgfHwgdmFsID09PSBcIlwiIHx8IHZhbC50cmltKCkgIT09IFwiZHJhZ1wiIHx8IGUuYnV0dG9ucyAhPT0gMSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBlLmRldGFpbCA9PT0gMTtcbn1cblxuZnVuY3Rpb24gc2V0UmVzaXphYmxlKHZhbHVlKSB7XG4gICAgcmVzaXphYmxlID0gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIGVuZERyYWcoKSB7XG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5jdXJzb3IgPSAnZGVmYXVsdCc7XG4gICAgc2hvdWxkRHJhZyA9IGZhbHNlO1xufVxuXG5mdW5jdGlvbiB0ZXN0UmVzaXplKCkge1xuICAgIGlmKCByZXNpemVFZGdlICkge1xuICAgICAgICBpbnZva2UoYHJlc2l6ZToke3Jlc2l6ZUVkZ2V9YCk7XG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gb25Nb3VzZURvd24oZSkge1xuICAgIGlmKElzV2luZG93cygpICYmIHRlc3RSZXNpemUoKSB8fCBkcmFnVGVzdChlKSkge1xuICAgICAgICBzaG91bGREcmFnID0gISFpc1ZhbGlkRHJhZyhlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzVmFsaWREcmFnKGUpIHtcbiAgICAvLyBJZ25vcmUgZHJhZyBvbiBzY3JvbGxiYXJzXG4gICAgcmV0dXJuICEoZS5vZmZzZXRYID4gZS50YXJnZXQuY2xpZW50V2lkdGggfHwgZS5vZmZzZXRZID4gZS50YXJnZXQuY2xpZW50SGVpZ2h0KTtcbn1cblxuZnVuY3Rpb24gb25Nb3VzZVVwKGUpIHtcbiAgICBsZXQgbW91c2VQcmVzc2VkID0gZS5idXR0b25zICE9PSB1bmRlZmluZWQgPyBlLmJ1dHRvbnMgOiBlLndoaWNoO1xuICAgIGlmIChtb3VzZVByZXNzZWQgPiAwKSB7XG4gICAgICAgIGVuZERyYWcoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHNldFJlc2l6ZShjdXJzb3IgPSBkZWZhdWx0Q3Vyc29yKSB7XG4gICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmN1cnNvciA9IGN1cnNvcjtcbiAgICByZXNpemVFZGdlID0gY3Vyc29yO1xufVxuXG5mdW5jdGlvbiBvbk1vdXNlTW92ZShlKSB7XG4gICAgc2hvdWxkRHJhZyA9IGNoZWNrRHJhZyhlKTtcbiAgICBpZiAoSXNXaW5kb3dzKCkgJiYgcmVzaXphYmxlKSB7XG4gICAgICAgIGhhbmRsZVJlc2l6ZShlKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrRHJhZyhlKSB7XG4gICAgbGV0IG1vdXNlUHJlc3NlZCA9IGUuYnV0dG9ucyAhPT0gdW5kZWZpbmVkID8gZS5idXR0b25zIDogZS53aGljaDtcbiAgICBpZihzaG91bGREcmFnICYmIG1vdXNlUHJlc3NlZCA+IDApIHtcbiAgICAgICAgaW52b2tlKFwiZHJhZ1wiKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gc2hvdWxkRHJhZztcbn1cblxuZnVuY3Rpb24gaGFuZGxlUmVzaXplKGUpIHtcbiAgICBsZXQgcmVzaXplSGFuZGxlSGVpZ2h0ID0gR2V0RmxhZyhcInN5c3RlbS5yZXNpemVIYW5kbGVIZWlnaHRcIikgfHwgNTtcbiAgICBsZXQgcmVzaXplSGFuZGxlV2lkdGggPSBHZXRGbGFnKFwic3lzdGVtLnJlc2l6ZUhhbmRsZVdpZHRoXCIpIHx8IDU7XG5cbiAgICAvLyBFeHRyYSBwaXhlbHMgZm9yIHRoZSBjb3JuZXIgYXJlYXNcbiAgICBsZXQgY29ybmVyRXh0cmEgPSBHZXRGbGFnKFwicmVzaXplQ29ybmVyRXh0cmFcIikgfHwgMTA7XG5cbiAgICBsZXQgcmlnaHRCb3JkZXIgPSB3aW5kb3cub3V0ZXJXaWR0aCAtIGUuY2xpZW50WCA8IHJlc2l6ZUhhbmRsZVdpZHRoO1xuICAgIGxldCBsZWZ0Qm9yZGVyID0gZS5jbGllbnRYIDwgcmVzaXplSGFuZGxlV2lkdGg7XG4gICAgbGV0IHRvcEJvcmRlciA9IGUuY2xpZW50WSA8IHJlc2l6ZUhhbmRsZUhlaWdodDtcbiAgICBsZXQgYm90dG9tQm9yZGVyID0gd2luZG93Lm91dGVySGVpZ2h0IC0gZS5jbGllbnRZIDwgcmVzaXplSGFuZGxlSGVpZ2h0O1xuXG4gICAgLy8gQWRqdXN0IGZvciBjb3JuZXJzXG4gICAgbGV0IHJpZ2h0Q29ybmVyID0gd2luZG93Lm91dGVyV2lkdGggLSBlLmNsaWVudFggPCAocmVzaXplSGFuZGxlV2lkdGggKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IGxlZnRDb3JuZXIgPSBlLmNsaWVudFggPCAocmVzaXplSGFuZGxlV2lkdGggKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IHRvcENvcm5lciA9IGUuY2xpZW50WSA8IChyZXNpemVIYW5kbGVIZWlnaHQgKyBjb3JuZXJFeHRyYSk7XG4gICAgbGV0IGJvdHRvbUNvcm5lciA9IHdpbmRvdy5vdXRlckhlaWdodCAtIGUuY2xpZW50WSA8IChyZXNpemVIYW5kbGVIZWlnaHQgKyBjb3JuZXJFeHRyYSk7XG5cbiAgICAvLyBJZiB3ZSBhcmVuJ3Qgb24gYW4gZWRnZSwgYnV0IHdlcmUsIHJlc2V0IHRoZSBjdXJzb3IgdG8gZGVmYXVsdFxuICAgIGlmICghbGVmdEJvcmRlciAmJiAhcmlnaHRCb3JkZXIgJiYgIXRvcEJvcmRlciAmJiAhYm90dG9tQm9yZGVyICYmIHJlc2l6ZUVkZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzZXRSZXNpemUoKTtcbiAgICB9XG4gICAgLy8gQWRqdXN0ZWQgZm9yIGNvcm5lciBhcmVhc1xuICAgIGVsc2UgaWYgKHJpZ2h0Q29ybmVyICYmIGJvdHRvbUNvcm5lcikgc2V0UmVzaXplKFwic2UtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRDb3JuZXIgJiYgYm90dG9tQ29ybmVyKSBzZXRSZXNpemUoXCJzdy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAobGVmdENvcm5lciAmJiB0b3BDb3JuZXIpIHNldFJlc2l6ZShcIm53LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BDb3JuZXIgJiYgcmlnaHRDb3JuZXIpIHNldFJlc2l6ZShcIm5lLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Qm9yZGVyKSBzZXRSZXNpemUoXCJ3LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BCb3JkZXIpIHNldFJlc2l6ZShcIm4tcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwicy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAocmlnaHRCb3JkZXIpIHNldFJlc2l6ZShcImUtcmVzaXplXCIpO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gUG9zaXRpb25cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIFggY29vcmRpbmF0ZS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBZIC0gVGhlIFkgY29vcmRpbmF0ZS5cbiAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IFNpemVcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBYIC0gVGhlIHdpZHRoLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFkgLSBUaGUgaGVpZ2h0LlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBSZWN0XG4gKiBAcHJvcGVydHkge251bWJlcn0gWCAtIFRoZSBYIGNvb3JkaW5hdGUgb2YgdGhlIHRvcC1sZWZ0IGNvcm5lci5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBZIC0gVGhlIFkgY29vcmRpbmF0ZSBvZiB0aGUgdG9wLWxlZnQgY29ybmVyLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSByZWN0YW5nbGUuXG4gKiBAcHJvcGVydHkge251bWJlcn0gSGVpZ2h0IC0gVGhlIGhlaWdodCBvZiB0aGUgcmVjdGFuZ2xlLlxuICovXG5cblxuLyoqXG4gKiBAdHlwZWRlZiB7KCdaZXJvJ3wnTmluZXR5J3wnT25lRWlnaHR5J3wnVHdvU2V2ZW50eScpfSBSb3RhdGlvblxuICogVGhlIHJvdGF0aW9uIG9mIHRoZSBzY3JlZW4uIENhbiBiZSBvbmUgb2YgJ1plcm8nLCAnTmluZXR5JywgJ09uZUVpZ2h0eScsICdUd29TZXZlbnR5Jy5cbiAqL1xuXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gU2NyZWVuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSWQgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHNjcmVlbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBOYW1lIC0gSHVtYW4gcmVhZGFibGUgbmFtZSBvZiB0aGUgc2NyZWVuLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IFNjYWxlIC0gVGhlIHJlc29sdXRpb24gc2NhbGUgb2YgdGhlIHNjcmVlbi4gMSA9IHN0YW5kYXJkIHJlc29sdXRpb24sIDIgPSBoaWdoIChSZXRpbmEpLCBldGMuXG4gKiBAcHJvcGVydHkge1Bvc2l0aW9ufSBQb3NpdGlvbiAtIENvbnRhaW5zIHRoZSBYIGFuZCBZIGNvb3JkaW5hdGVzIG9mIHRoZSBzY3JlZW4ncyBwb3NpdGlvbi5cbiAqIEBwcm9wZXJ0eSB7U2l6ZX0gU2l6ZSAtIENvbnRhaW5zIHRoZSB3aWR0aCBhbmQgaGVpZ2h0IG9mIHRoZSBzY3JlZW4uXG4gKiBAcHJvcGVydHkge1JlY3R9IEJvdW5kcyAtIENvbnRhaW5zIHRoZSBib3VuZHMgb2YgdGhlIHNjcmVlbiBpbiB0ZXJtcyBvZiBYLCBZLCBXaWR0aCwgYW5kIEhlaWdodC5cbiAqIEBwcm9wZXJ0eSB7UmVjdH0gV29ya0FyZWEgLSBDb250YWlucyB0aGUgYXJlYSBvZiB0aGUgc2NyZWVuIHRoYXQgaXMgYWN0dWFsbHkgdXNhYmxlIChleGNsdWRpbmcgdGFza2JhciBhbmQgb3RoZXIgc3lzdGVtIFVJKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gSXNQcmltYXJ5IC0gVHJ1ZSBpZiB0aGlzIGlzIHRoZSBwcmltYXJ5IG1vbml0b3Igc2VsZWN0ZWQgYnkgdGhlIHVzZXIgaW4gdGhlIG9wZXJhdGluZyBzeXN0ZW0uXG4gKiBAcHJvcGVydHkge1JvdGF0aW9ufSBSb3RhdGlvbiAtIFRoZSByb3RhdGlvbiBvZiB0aGUgc2NyZWVuLlxuICovXG5cblxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuU2NyZWVucywgJycpO1xuXG5jb25zdCBnZXRBbGwgPSAwO1xuY29uc3QgZ2V0UHJpbWFyeSA9IDE7XG5jb25zdCBnZXRDdXJyZW50ID0gMjtcblxuLyoqXG4gKiBHZXRzIGFsbCBzY3JlZW5zLlxuICogQHJldHVybnMge1Byb21pc2U8U2NyZWVuW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiBTY3JlZW4gb2JqZWN0cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldEFsbCgpIHtcbiAgICByZXR1cm4gY2FsbChnZXRBbGwpO1xufVxuLyoqXG4gKiBHZXRzIHRoZSBwcmltYXJ5IHNjcmVlbi5cbiAqIEByZXR1cm5zIHtQcm9taXNlPFNjcmVlbj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBwcmltYXJ5IHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldFByaW1hcnkoKSB7XG4gICAgcmV0dXJuIGNhbGwoZ2V0UHJpbWFyeSk7XG59XG4vKipcbiAqIEdldHMgdGhlIGN1cnJlbnQgYWN0aXZlIHNjcmVlbi5cbiAqXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxTY3JlZW4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjdXJyZW50IGFjdGl2ZSBzY3JlZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRDdXJyZW50KCkge1xuICAgIHJldHVybiBjYWxsKGdldEN1cnJlbnQpO1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vLyBJbXBvcnQgc2NyZWVuIGpzZG9jIGRlZmluaXRpb24gZnJvbSAuL3NjcmVlbnMuanNcbi8qKlxuICogQHR5cGVkZWYge2ltcG9ydChcIi4vc2NyZWVuc1wiKS5TY3JlZW59IFNjcmVlblxuICovXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlcldpdGhJRCwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWVcIjtcblxuY29uc3QgY2VudGVyID0gMDtcbmNvbnN0IHNldFRpdGxlID0gMTtcbmNvbnN0IGZ1bGxzY3JlZW4gPSAyO1xuY29uc3QgdW5GdWxsc2NyZWVuID0gMztcbmNvbnN0IHNldFNpemUgPSA0O1xuY29uc3Qgc2l6ZSA9IDU7XG5jb25zdCBzZXRNYXhTaXplID0gNjtcbmNvbnN0IHNldE1pblNpemUgPSA3O1xuY29uc3Qgc2V0QWx3YXlzT25Ub3AgPSA4O1xuY29uc3Qgc2V0UmVsYXRpdmVQb3NpdGlvbiA9IDk7XG5jb25zdCByZWxhdGl2ZVBvc2l0aW9uID0gMTA7XG5jb25zdCBzY3JlZW4gPSAxMTtcbmNvbnN0IGhpZGUgPSAxMjtcbmNvbnN0IG1heGltaXNlID0gMTM7XG5jb25zdCB1bk1heGltaXNlID0gMTQ7XG5jb25zdCB0b2dnbGVNYXhpbWlzZSA9IDE1O1xuY29uc3QgbWluaW1pc2UgPSAxNjtcbmNvbnN0IHVuTWluaW1pc2UgPSAxNztcbmNvbnN0IHJlc3RvcmUgPSAxODtcbmNvbnN0IHNob3cgPSAxOTtcbmNvbnN0IGNsb3NlID0gMjA7XG5jb25zdCBzZXRCYWNrZ3JvdW5kQ29sb3VyID0gMjE7XG5jb25zdCBzZXRSZXNpemFibGUgPSAyMjtcbmNvbnN0IHdpZHRoID0gMjM7XG5jb25zdCBoZWlnaHQgPSAyNDtcbmNvbnN0IHpvb21JbiA9IDI1O1xuY29uc3Qgem9vbU91dCA9IDI2O1xuY29uc3Qgem9vbVJlc2V0ID0gMjc7XG5jb25zdCBnZXRab29tTGV2ZWwgPSAyODtcbmNvbnN0IHNldFpvb21MZXZlbCA9IDI5O1xuXG5jb25zdCB0aGlzV2luZG93ID0gR2V0KCcnKTtcblxuZnVuY3Rpb24gY3JlYXRlV2luZG93KGNhbGwpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBHZXQ6ICh3aW5kb3dOYW1lKSA9PiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKSxcbiAgICAgICAgQ2VudGVyOiAoKSA9PiBjYWxsKGNlbnRlciksXG4gICAgICAgIFNldFRpdGxlOiAodGl0bGUpID0+IGNhbGwoc2V0VGl0bGUsIHt0aXRsZX0pLFxuICAgICAgICBGdWxsc2NyZWVuOiAoKSA9PiBjYWxsKGZ1bGxzY3JlZW4pLFxuICAgICAgICBVbkZ1bGxzY3JlZW46ICgpID0+IGNhbGwodW5GdWxsc2NyZWVuKSxcbiAgICAgICAgU2V0U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2l6ZTogKCkgPT4gY2FsbChzaXplKSxcbiAgICAgICAgU2V0TWF4U2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWF4U2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2V0TWluU2l6ZTogKHdpZHRoLCBoZWlnaHQpID0+IGNhbGwoc2V0TWluU2l6ZSwge3dpZHRoLCBoZWlnaHR9KSxcbiAgICAgICAgU2V0QWx3YXlzT25Ub3A6IChvblRvcCkgPT4gY2FsbChzZXRBbHdheXNPblRvcCwge2Fsd2F5c09uVG9wOiBvblRvcH0pLFxuICAgICAgICBTZXRSZWxhdGl2ZVBvc2l0aW9uOiAoeCwgeSkgPT4gY2FsbChzZXRSZWxhdGl2ZVBvc2l0aW9uLCB7eCwgeX0pLFxuICAgICAgICBSZWxhdGl2ZVBvc2l0aW9uOiAoKSA9PiBjYWxsKHJlbGF0aXZlUG9zaXRpb24pLFxuICAgICAgICBTY3JlZW46ICgpID0+IGNhbGwoc2NyZWVuKSxcbiAgICAgICAgSGlkZTogKCkgPT4gY2FsbChoaWRlKSxcbiAgICAgICAgTWF4aW1pc2U6ICgpID0+IGNhbGwobWF4aW1pc2UpLFxuICAgICAgICBVbk1heGltaXNlOiAoKSA9PiBjYWxsKHVuTWF4aW1pc2UpLFxuICAgICAgICBUb2dnbGVNYXhpbWlzZTogKCkgPT4gY2FsbCh0b2dnbGVNYXhpbWlzZSksXG4gICAgICAgIE1pbmltaXNlOiAoKSA9PiBjYWxsKG1pbmltaXNlKSxcbiAgICAgICAgVW5NaW5pbWlzZTogKCkgPT4gY2FsbCh1bk1pbmltaXNlKSxcbiAgICAgICAgUmVzdG9yZTogKCkgPT4gY2FsbChyZXN0b3JlKSxcbiAgICAgICAgU2hvdzogKCkgPT4gY2FsbChzaG93KSxcbiAgICAgICAgQ2xvc2U6ICgpID0+IGNhbGwoY2xvc2UpLFxuICAgICAgICBTZXRCYWNrZ3JvdW5kQ29sb3VyOiAociwgZywgYiwgYSkgPT4gY2FsbChzZXRCYWNrZ3JvdW5kQ29sb3VyLCB7ciwgZywgYiwgYX0pLFxuICAgICAgICBTZXRSZXNpemFibGU6IChyZXNpemFibGUpID0+IGNhbGwoc2V0UmVzaXphYmxlLCB7cmVzaXphYmxlfSksXG4gICAgICAgIFdpZHRoOiAoKSA9PiBjYWxsKHdpZHRoKSxcbiAgICAgICAgSGVpZ2h0OiAoKSA9PiBjYWxsKGhlaWdodCksXG4gICAgICAgIFpvb21JbjogKCkgPT4gY2FsbCh6b29tSW4pLFxuICAgICAgICBab29tT3V0OiAoKSA9PiBjYWxsKHpvb21PdXQpLFxuICAgICAgICBab29tUmVzZXQ6ICgpID0+IGNhbGwoem9vbVJlc2V0KSxcbiAgICAgICAgR2V0Wm9vbUxldmVsOiAoKSA9PiBjYWxsKGdldFpvb21MZXZlbCksXG4gICAgICAgIFNldFpvb21MZXZlbDogKHpvb21MZXZlbCkgPT4gY2FsbChzZXRab29tTGV2ZWwsIHt6b29tTGV2ZWx9KSxcbiAgICB9O1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNwZWNpZmllZCB3aW5kb3cuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHdpbmRvd05hbWUgLSBUaGUgbmFtZSBvZiB0aGUgd2luZG93IHRvIGdldC5cbiAqIEByZXR1cm4ge09iamVjdH0gLSBUaGUgc3BlY2lmaWVkIHdpbmRvdyBvYmplY3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXQod2luZG93TmFtZSkge1xuICAgIHJldHVybiBjcmVhdGVXaW5kb3cobmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5XaW5kb3csIHdpbmRvd05hbWUpKTtcbn1cblxuLyoqXG4gKiBDZW50ZXJzIHRoZSB3aW5kb3cgb24gdGhlIHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENlbnRlcigpIHtcbiAgICB0aGlzV2luZG93LkNlbnRlcigpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIHRpdGxlIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGUgLSBUaGUgdGl0bGUgdG8gc2V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0VGl0bGUodGl0bGUpIHtcbiAgICB0aGlzV2luZG93LlNldFRpdGxlKHRpdGxlKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSB3aW5kb3cgdG8gZnVsbHNjcmVlbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEZ1bGxzY3JlZW4oKSB7XG4gICAgdGhpc1dpbmRvdy5GdWxsc2NyZWVuKCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgc2l6ZSBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdGhpc1dpbmRvdy5TZXRTaXplKHdpZHRoLCBoZWlnaHQpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNpemUoKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2l6ZSgpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoIC0gVGhlIG1heGltdW0gd2lkdGggb2YgdGhlIHdpbmRvdy5cbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHQgLSBUaGUgbWF4aW11bSBoZWlnaHQgb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldE1heFNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIHRoaXNXaW5kb3cuU2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBtaW5pbXVtIHNpemUgb2YgdGhlIHdpbmRvdy5cbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aCAtIFRoZSBtaW5pbXVtIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0IC0gVGhlIG1pbmltdW0gaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpIHtcbiAgICB0aGlzV2luZG93LlNldE1pblNpemUod2lkdGgsIGhlaWdodCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgd2luZG93IHRvIGFsd2F5cyBiZSBvbiB0b3AuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IG9uVG9wIC0gV2hldGhlciB0aGUgd2luZG93IHNob3VsZCBhbHdheXMgYmUgb24gdG9wLlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0QWx3YXlzT25Ub3Aob25Ub3ApIHtcbiAgICB0aGlzV2luZG93LlNldEFsd2F5c09uVG9wKG9uVG9wKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSByZWxhdGl2ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHggLSBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSB3aW5kb3cncyBwb3NpdGlvbi5cbiAqIEBwYXJhbSB7bnVtYmVyfSB5IC0gVGhlIHktY29vcmRpbmF0ZSBvZiB0aGUgd2luZG93J3MgcG9zaXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRSZWxhdGl2ZVBvc2l0aW9uKHgsIHkpIHtcbiAgICB0aGlzV2luZG93LlNldFJlbGF0aXZlUG9zaXRpb24oeCwgeSk7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFJlbGF0aXZlUG9zaXRpb24oKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuUmVsYXRpdmVQb3NpdGlvbigpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHNjcmVlbiB0aGF0IHRoZSB3aW5kb3cgaXMgb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTY3JlZW4oKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuU2NyZWVuKCk7XG59XG5cbi8qKlxuICogSGlkZXMgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XG4gICAgdGhpc1dpbmRvdy5IaWRlKCk7XG59XG5cbi8qKlxuICogTWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBNYXhpbWlzZSgpIHtcbiAgICB0aGlzV2luZG93Lk1heGltaXNlKCk7XG59XG5cbi8qKlxuICogVW4tbWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBVbk1heGltaXNlKCkge1xuICAgIHRoaXNXaW5kb3cuVW5NYXhpbWlzZSgpO1xufVxuXG4vKipcbiAqIFRvZ2dsZXMgdGhlIG1heGltaXNhdGlvbiBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gVG9nZ2xlTWF4aW1pc2UoKSB7XG4gICAgdGhpc1dpbmRvdy5Ub2dnbGVNYXhpbWlzZSgpO1xufVxuXG4vKipcbiAqIE1pbmltaXNlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gTWluaW1pc2UoKSB7XG4gICAgdGhpc1dpbmRvdy5NaW5pbWlzZSgpO1xufVxuXG4vKipcbiAqIFVuLW1pbmltaXNlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gVW5NaW5pbWlzZSgpIHtcbiAgICB0aGlzV2luZG93LlVuTWluaW1pc2UoKTtcbn1cblxuLyoqXG4gKiBSZXN0b3JlcyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVzdG9yZSgpIHtcbiAgICB0aGlzV2luZG93LlJlc3RvcmUoKTtcbn1cblxuLyoqXG4gKiBTaG93cyB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpIHtcbiAgICB0aGlzV2luZG93LlNob3coKTtcbn1cblxuLyoqXG4gKiBDbG9zZXMgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENsb3NlKCkge1xuICAgIHRoaXNXaW5kb3cuQ2xvc2UoKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBiYWNrZ3JvdW5kIGNvbG91ciBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHIgLSBUaGUgcmVkIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxuICogQHBhcmFtIHtudW1iZXJ9IGcgLSBUaGUgZ3JlZW4gY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXG4gKiBAcGFyYW0ge251bWJlcn0gYiAtIFRoZSBibHVlIGNvbXBvbmVudCBvZiB0aGUgY29sb3VyLlxuICogQHBhcmFtIHtudW1iZXJ9IGEgLSBUaGUgYWxwaGEgY29tcG9uZW50IG9mIHRoZSBjb2xvdXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRCYWNrZ3JvdW5kQ29sb3VyKHIsIGcsIGIsIGEpIHtcbiAgICB0aGlzV2luZG93LlNldEJhY2tncm91bmRDb2xvdXIociwgZywgYiwgYSk7XG59XG5cbi8qKlxuICogU2V0cyB3aGV0aGVyIHRoZSB3aW5kb3cgaXMgcmVzaXphYmxlLlxuICogQHBhcmFtIHtib29sZWFufSByZXNpemFibGUgLSBXaGV0aGVyIHRoZSB3aW5kb3cgc2hvdWxkIGJlIHJlc2l6YWJsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldFJlc2l6YWJsZShyZXNpemFibGUpIHtcbiAgICB0aGlzV2luZG93LlNldFJlc2l6YWJsZShyZXNpemFibGUpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaWR0aCgpIHtcbiAgICByZXR1cm4gdGhpc1dpbmRvdy5XaWR0aCgpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICovXG5leHBvcnQgZnVuY3Rpb24gSGVpZ2h0KCkge1xuICAgIHJldHVybiB0aGlzV2luZG93LkhlaWdodCgpO1xufVxuXG4vKipcbiAqIFpvb21zIGluIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBab29tSW4oKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tSW4oKTtcbn1cblxuLyoqXG4gKiBab29tcyBvdXQgdGhlIHdpbmRvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFpvb21PdXQoKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tT3V0KCk7XG59XG5cbi8qKlxuICogUmVzZXRzIHRoZSB6b29tIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBab29tUmVzZXQoKSB7XG4gICAgdGhpc1dpbmRvdy5ab29tUmVzZXQoKTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB3aW5kb3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRab29tTGV2ZWwoKSB7XG4gICAgcmV0dXJuIHRoaXNXaW5kb3cuR2V0Wm9vbUxldmVsKCk7XG59XG5cbi8qKlxuICogU2V0cyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgd2luZG93LlxuICogQHBhcmFtIHtudW1iZXJ9IHpvb21MZXZlbCAtIFRoZSB6b29tIGxldmVsIHRvIHNldC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFNldFpvb21MZXZlbCh6b29tTGV2ZWwpIHtcbiAgICB0aGlzV2luZG93LlNldFpvb21MZXZlbCh6b29tTGV2ZWwpO1xufVxuIiwgIlxuaW1wb3J0IHtFbWl0LCBXYWlsc0V2ZW50fSBmcm9tIFwiLi9ldmVudHNcIjtcbmltcG9ydCB7UXVlc3Rpb259IGZyb20gXCIuL2RpYWxvZ3NcIjtcbmltcG9ydCB7R2V0fSBmcm9tIFwiLi93aW5kb3dcIjtcbmltcG9ydCB7T3BlblVSTH0gZnJvbSBcIi4vYnJvd3NlclwiO1xuXG4vKipcbiAqIFNlbmRzIGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIG9wdGlvbmFsIGRhdGEuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBzZW5kLlxuICogQHBhcmFtIHthbnl9IFtkYXRhPW51bGxdIC0gT3B0aW9uYWwgZGF0YSB0byBzZW5kIGFsb25nIHdpdGggdGhlIGV2ZW50LlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHNlbmRFdmVudChldmVudE5hbWUsIGRhdGE9bnVsbCkge1xuICAgIGxldCBldmVudCA9IG5ldyBXYWlsc0V2ZW50KGV2ZW50TmFtZSwgZGF0YSk7XG4gICAgRW1pdChldmVudCk7XG59XG5cbi8qKlxuICogQWRkcyBldmVudCBsaXN0ZW5lcnMgdG8gZWxlbWVudHMgd2l0aCBgd21sLWV2ZW50YCBhdHRyaWJ1dGUuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gYWRkV01MRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLWV2ZW50XScpO1xuICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZXZlbnRUeXBlID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1ldmVudCcpO1xuICAgICAgICBjb25zdCBjb25maXJtID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1jb25maXJtJyk7XG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XG5cbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIERldGFjaGVkOiBmYWxzZSwgQnV0dG9uczpbe0xhYmVsOlwiWWVzXCJ9LHtMYWJlbDpcIk5vXCIsIElzRGVmYXVsdDp0cnVlfV19KS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3VsdCAhPT0gXCJOb1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZW5kRXZlbnQoZXZlbnRUeXBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNlbmRFdmVudChldmVudFR5cGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFJlbW92ZSBleGlzdGluZyBsaXN0ZW5lcnNcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcblxuICAgICAgICAvLyBBZGQgbmV3IGxpc3RlbmVyXG4gICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XG4gICAgfSk7XG59XG5cblxuLyoqXG4gKiBDYWxscyBhIG1ldGhvZCBvbiBhIHNwZWNpZmllZCB3aW5kb3cuXG4gKiBAcGFyYW0ge3N0cmluZ30gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgdG8gY2FsbCB0aGUgbWV0aG9kIG9uLlxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZCAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqL1xuZnVuY3Rpb24gY2FsbFdpbmRvd01ldGhvZCh3aW5kb3dOYW1lLCBtZXRob2QpIHtcbiAgICBsZXQgdGFyZ2V0V2luZG93ID0gR2V0KHdpbmRvd05hbWUpO1xuICAgIGxldCBtZXRob2RNYXAgPSBXaW5kb3dNZXRob2RzKHRhcmdldFdpbmRvdyk7XG4gICAgaWYgKCFtZXRob2RNYXAuaGFzKG1ldGhvZCkpIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJXaW5kb3cgbWV0aG9kIFwiICsgbWV0aG9kICsgXCIgbm90IGZvdW5kXCIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBtZXRob2RNYXAuZ2V0KG1ldGhvZCkoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBjYWxsaW5nIHdpbmRvdyBtZXRob2QgJ1wiICsgbWV0aG9kICsgXCInOiBcIiArIGUpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBZGRzIHdpbmRvdyBsaXN0ZW5lcnMgZm9yIGVsZW1lbnRzIHdpdGggdGhlICd3bWwtd2luZG93JyBhdHRyaWJ1dGUuXG4gKiBSZW1vdmVzIGFueSBleGlzdGluZyBsaXN0ZW5lcnMgYmVmb3JlIGFkZGluZyBuZXcgb25lcy5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5mdW5jdGlvbiBhZGRXTUxXaW5kb3dMaXN0ZW5lcnMoKSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbd21sLXdpbmRvd10nKTtcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IHdpbmRvd01ldGhvZCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtd2luZG93Jyk7XG4gICAgICAgIGNvbnN0IGNvbmZpcm0gPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWNvbmZpcm0nKTtcbiAgICAgICAgY29uc3QgdHJpZ2dlciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdHJpZ2dlcicpIHx8ICdjbGljayc7XG4gICAgICAgIGNvbnN0IHRhcmdldFdpbmRvdyA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtdGFyZ2V0LXdpbmRvdycpIHx8ICcnO1xuXG4gICAgICAgIGxldCBjYWxsYmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChjb25maXJtKSB7XG4gICAgICAgICAgICAgICAgUXVlc3Rpb24oe1RpdGxlOiBcIkNvbmZpcm1cIiwgTWVzc2FnZTpjb25maXJtLCBCdXR0b25zOlt7TGFiZWw6XCJZZXNcIn0se0xhYmVsOlwiTm9cIiwgSXNEZWZhdWx0OnRydWV9XX0pLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0ICE9PSBcIk5vXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxXaW5kb3dNZXRob2QodGFyZ2V0V2luZG93LCB3aW5kb3dNZXRob2QpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FsbFdpbmRvd01ldGhvZCh0YXJnZXRXaW5kb3csIHdpbmRvd01ldGhvZCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUmVtb3ZlIGV4aXN0aW5nIGxpc3RlbmVyc1xuICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xuXG4gICAgICAgIC8vIEFkZCBuZXcgbGlzdGVuZXJcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHRyaWdnZXIsIGNhbGxiYWNrKTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBBZGRzIGEgbGlzdGVuZXIgdG8gZWxlbWVudHMgd2l0aCB0aGUgJ3dtbC1vcGVudXJsJyBhdHRyaWJ1dGUuXG4gKiBXaGVuIHRoZSBzcGVjaWZpZWQgdHJpZ2dlciBldmVudCBpcyBmaXJlZCBvbiBhbnkgb2YgdGhlc2UgZWxlbWVudHMsXG4gKiB0aGUgbGlzdGVuZXIgd2lsbCBvcGVuIHRoZSBVUkwgc3BlY2lmaWVkIGJ5IHRoZSAnd21sLW9wZW51cmwnIGF0dHJpYnV0ZS5cbiAqIElmIGEgJ3dtbC1jb25maXJtJyBhdHRyaWJ1dGUgaXMgcHJvdmlkZWQsIGEgY29uZmlybWF0aW9uIGRpYWxvZyB3aWxsIGJlIGRpc3BsYXllZCxcbiAqIGFuZCB0aGUgVVJMIHdpbGwgb25seSBiZSBvcGVuZWQgaWYgdGhlIHVzZXIgY29uZmlybXMuXG4gKlxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpIHtcbiAgICBjb25zdCBlbGVtZW50cyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ1t3bWwtb3BlbnVybF0nKTtcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IHVybCA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtb3BlbnVybCcpO1xuICAgICAgICBjb25zdCBjb25maXJtID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1jb25maXJtJyk7XG4gICAgICAgIGNvbnN0IHRyaWdnZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCI7XG5cbiAgICAgICAgbGV0IGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGNvbmZpcm0pIHtcbiAgICAgICAgICAgICAgICBRdWVzdGlvbih7VGl0bGU6IFwiQ29uZmlybVwiLCBNZXNzYWdlOmNvbmZpcm0sIEJ1dHRvbnM6W3tMYWJlbDpcIlllc1wifSx7TGFiZWw6XCJOb1wiLCBJc0RlZmF1bHQ6dHJ1ZX1dfSkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgIT09IFwiTm9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCBPcGVuVVJMKHVybCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2b2lkIE9wZW5VUkwodXJsKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZW1vdmUgZXhpc3RpbmcgbGlzdGVuZXJzXG4gICAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBjYWxsYmFjayk7XG5cbiAgICAgICAgLy8gQWRkIG5ldyBsaXN0ZW5lclxuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIodHJpZ2dlciwgY2FsbGJhY2spO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIFJlbG9hZHMgdGhlIFdNTCBwYWdlIGJ5IGFkZGluZyBuZWNlc3NhcnkgZXZlbnQgbGlzdGVuZXJzIGFuZCBicm93c2VyIGxpc3RlbmVycy5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gUmVsb2FkKCkge1xuICAgIGFkZFdNTEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgYWRkV01MV2luZG93TGlzdGVuZXJzKCk7XG4gICAgYWRkV01MT3BlbkJyb3dzZXJMaXN0ZW5lcigpO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBtYXAgb2YgYWxsIG1ldGhvZHMgaW4gdGhlIGN1cnJlbnQgd2luZG93LlxuICogQHJldHVybnMge01hcH0gLSBBIG1hcCBvZiB3aW5kb3cgbWV0aG9kcy5cbiAqL1xuZnVuY3Rpb24gV2luZG93TWV0aG9kcyh0YXJnZXRXaW5kb3cpIHtcbiAgICAvLyBDcmVhdGUgYSBuZXcgbWFwIHRvIHN0b3JlIG1ldGhvZHNcbiAgICBsZXQgcmVzdWx0ID0gbmV3IE1hcCgpO1xuXG4gICAgLy8gSXRlcmF0ZSBvdmVyIGFsbCBwcm9wZXJ0aWVzIG9mIHRoZSB3aW5kb3cgb2JqZWN0XG4gICAgZm9yIChsZXQgbWV0aG9kIGluIHRhcmdldFdpbmRvdykge1xuICAgICAgICAvLyBDaGVjayBpZiB0aGUgcHJvcGVydHkgaXMgaW5kZWVkIGEgbWV0aG9kIChmdW5jdGlvbilcbiAgICAgICAgaWYodHlwZW9mIHRhcmdldFdpbmRvd1ttZXRob2RdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAvLyBBZGQgdGhlIG1ldGhvZCB0byB0aGUgbWFwXG4gICAgICAgICAgICByZXN1bHQuc2V0KG1ldGhvZCwgdGFyZ2V0V2luZG93W21ldGhvZF0pO1xuICAgICAgICB9XG5cbiAgICB9XG4gICAgLy8gUmV0dXJuIHRoZSBtYXAgb2Ygd2luZG93IG1ldGhvZHNcbiAgICByZXR1cm4gcmVzdWx0O1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtpbXBvcnQoXCIuL3R5cGVzXCIpLldhaWxzRXZlbnR9IFdhaWxzRXZlbnRcbiAqL1xuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuXG5pbXBvcnQge0V2ZW50VHlwZXN9IGZyb20gXCIuL2V2ZW50X3R5cGVzXCI7XG5leHBvcnQgY29uc3QgVHlwZXMgPSBFdmVudFR5cGVzO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLmRpc3BhdGNoV2FpbHNFdmVudCA9IGRpc3BhdGNoV2FpbHNFdmVudDtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuRXZlbnRzLCAnJyk7XG5jb25zdCBFbWl0TWV0aG9kID0gMDtcbmNvbnN0IGV2ZW50TGlzdGVuZXJzID0gbmV3IE1hcCgpO1xuXG5jbGFzcyBMaXN0ZW5lciB7XG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgICAgIHRoaXMuZXZlbnROYW1lID0gZXZlbnROYW1lO1xuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICAgICAgdGhpcy5DYWxsYmFjayA9IChkYXRhKSA9PiB7XG4gICAgICAgICAgICBjYWxsYmFjayhkYXRhKTtcbiAgICAgICAgICAgIGlmICh0aGlzLm1heENhbGxiYWNrcyA9PT0gLTEpIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMubWF4Q2FsbGJhY2tzIC09IDE7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXhDYWxsYmFja3MgPT09IDA7XG4gICAgICAgIH07XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgV2FpbHNFdmVudCB7XG4gICAgY29uc3RydWN0b3IobmFtZSwgZGF0YSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cCgpIHtcbn1cblxuZnVuY3Rpb24gZGlzcGF0Y2hXYWlsc0V2ZW50KGV2ZW50KSB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudC5uYW1lKTtcbiAgICBpZiAobGlzdGVuZXJzKSB7XG4gICAgICAgIGxldCB0b1JlbW92ZSA9IGxpc3RlbmVycy5maWx0ZXIobGlzdGVuZXIgPT4ge1xuICAgICAgICAgICAgbGV0IHJlbW92ZSA9IGxpc3RlbmVyLkNhbGxiYWNrKGV2ZW50KTtcbiAgICAgICAgICAgIGlmIChyZW1vdmUpIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHRvUmVtb3ZlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGxpc3RlbmVycyA9IGxpc3RlbmVycy5maWx0ZXIobCA9PiAhdG9SZW1vdmUuaW5jbHVkZXMobCkpO1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVycy5sZW5ndGggPT09IDApIGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudC5uYW1lKTtcbiAgICAgICAgICAgIGVsc2UgZXZlbnRMaXN0ZW5lcnMuc2V0KGV2ZW50Lm5hbWUsIGxpc3RlbmVycyk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogUmVnaXN0ZXIgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgbXVsdGlwbGUgdGltZXMgZm9yIGEgc3BlY2lmaWMgZXZlbnQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZWdpc3RlciB0aGUgY2FsbGJhY2sgZm9yLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGV2ZW50IGlzIHRyaWdnZXJlZC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3MgLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdGhlIGNhbGxiYWNrIGNhbiBiZSBjYWxsZWQgZm9yIHRoZSBldmVudC4gT25jZSB0aGUgbWF4aW11bSBudW1iZXIgaXMgcmVhY2hlZCwgdGhlIGNhbGxiYWNrIHdpbGwgbm8gbG9uZ2VyIGJlIGNhbGxlZC5cbiAqXG4gQHJldHVybiB7ZnVuY3Rpb259IC0gQSBmdW5jdGlvbiB0aGF0LCB3aGVuIGNhbGxlZCwgd2lsbCB1bnJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmcm9tIHRoZSBldmVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKSB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChldmVudE5hbWUpIHx8IFtdO1xuICAgIGNvbnN0IHRoaXNMaXN0ZW5lciA9IG5ldyBMaXN0ZW5lcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpO1xuICAgIGxpc3RlbmVycy5wdXNoKHRoaXNMaXN0ZW5lcik7XG4gICAgZXZlbnRMaXN0ZW5lcnMuc2V0KGV2ZW50TmFtZSwgbGlzdGVuZXJzKTtcbiAgICByZXR1cm4gKCkgPT4gbGlzdGVuZXJPZmYodGhpc0xpc3RlbmVyKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuIHRoZSBzcGVjaWZpZWQgZXZlbnQgb2NjdXJzLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQuXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFjayAtIFRoZSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZC4gSXQgdGFrZXMgbm8gcGFyYW1ldGVycy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuICovXG5leHBvcnQgZnVuY3Rpb24gT24oZXZlbnROYW1lLCBjYWxsYmFjaykgeyByZXR1cm4gT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAtMSk7IH1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmx5IG9uY2UgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudC5cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIC0gVGhlIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGV2ZW50IG9jY3Vycy5cbiAqIEByZXR1cm4ge2Z1bmN0aW9ufSAtIEEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsIHdpbGwgdW5yZWdpc3RlciB0aGUgY2FsbGJhY2sgZnJvbSB0aGUgZXZlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHsgcmV0dXJuIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgMSk7IH1cblxuLyoqXG4gKiBSZW1vdmVzIHRoZSBzcGVjaWZpZWQgbGlzdGVuZXIgZnJvbSB0aGUgZXZlbnQgbGlzdGVuZXJzIGNvbGxlY3Rpb24uXG4gKiBJZiBhbGwgbGlzdGVuZXJzIGZvciB0aGUgZXZlbnQgYXJlIHJlbW92ZWQsIHRoZSBldmVudCBrZXkgaXMgZGVsZXRlZCBmcm9tIHRoZSBjb2xsZWN0aW9uLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBsaXN0ZW5lciAtIFRoZSBsaXN0ZW5lciB0byBiZSByZW1vdmVkLlxuICovXG5mdW5jdGlvbiBsaXN0ZW5lck9mZihsaXN0ZW5lcikge1xuICAgIGNvbnN0IGV2ZW50TmFtZSA9IGxpc3RlbmVyLmV2ZW50TmFtZTtcbiAgICBsZXQgbGlzdGVuZXJzID0gZXZlbnRMaXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSkuZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuICAgIGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSBldmVudExpc3RlbmVycy5kZWxldGUoZXZlbnROYW1lKTtcbiAgICBlbHNlIGV2ZW50TGlzdGVuZXJzLnNldChldmVudE5hbWUsIGxpc3RlbmVycyk7XG59XG5cblxuLyoqXG4gKiBSZW1vdmVzIGV2ZW50IGxpc3RlbmVycyBmb3IgdGhlIHNwZWNpZmllZCBldmVudCBuYW1lcy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHJlbW92ZSBsaXN0ZW5lcnMgZm9yLlxuICogQHBhcmFtIHsuLi5zdHJpbmd9IGFkZGl0aW9uYWxFdmVudE5hbWVzIC0gQWRkaXRpb25hbCBldmVudCBuYW1lcyB0byByZW1vdmUgbGlzdGVuZXJzIGZvci5cbiAqIEByZXR1cm4ge3VuZGVmaW5lZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9mZihldmVudE5hbWUsIC4uLmFkZGl0aW9uYWxFdmVudE5hbWVzKSB7XG4gICAgbGV0IGV2ZW50c1RvUmVtb3ZlID0gW2V2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXNdO1xuICAgIGV2ZW50c1RvUmVtb3ZlLmZvckVhY2goZXZlbnROYW1lID0+IGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudE5hbWUpKTtcbn1cbi8qKlxuICogUmVtb3ZlcyBhbGwgZXZlbnQgbGlzdGVuZXJzLlxuICpcbiAqIEBmdW5jdGlvbiBPZmZBbGxcbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZnVuY3Rpb24gT2ZmQWxsKCkgeyBldmVudExpc3RlbmVycy5jbGVhcigpOyB9XG5cbi8qKlxuICogRW1pdHMgYW4gZXZlbnQgdXNpbmcgdGhlIGdpdmVuIGV2ZW50IG5hbWUuXG4gKlxuICogQHBhcmFtIHtXYWlsc0V2ZW50fSBldmVudCAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byBlbWl0LlxuICogQHJldHVybnMge2FueX0gLSBUaGUgcmVzdWx0IG9mIHRoZSBlbWl0dGVkIGV2ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gRW1pdChldmVudCkgeyByZXR1cm4gY2FsbChFbWl0TWV0aG9kLCBldmVudCk7IH1cbiIsICJcbmV4cG9ydCBjb25zdCBFdmVudFR5cGVzID0ge1xuXHRXaW5kb3dzOiB7XG5cdFx0U3lzdGVtVGhlbWVDaGFuZ2VkOiBcIndpbmRvd3M6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdFx0QVBNUG93ZXJTdGF0dXNDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclN0YXR1c0NoYW5nZVwiLFxuXHRcdEFQTVN1c3BlbmQ6IFwid2luZG93czpBUE1TdXNwZW5kXCIsXG5cdFx0QVBNUmVzdW1lQXV0b21hdGljOiBcIndpbmRvd3M6QVBNUmVzdW1lQXV0b21hdGljXCIsXG5cdFx0QVBNUmVzdW1lU3VzcGVuZDogXCJ3aW5kb3dzOkFQTVJlc3VtZVN1c3BlbmRcIixcblx0XHRBUE1Qb3dlclNldHRpbmdDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclNldHRpbmdDaGFuZ2VcIixcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwid2luZG93czpBcHBsaWNhdGlvblN0YXJ0ZWRcIixcblx0XHRXZWJWaWV3TmF2aWdhdGlvbkNvbXBsZXRlZDogXCJ3aW5kb3dzOldlYlZpZXdOYXZpZ2F0aW9uQ29tcGxldGVkXCIsXG5cdFx0V2luZG93SW5hY3RpdmU6IFwid2luZG93czpXaW5kb3dJbmFjdGl2ZVwiLFxuXHRcdFdpbmRvd0FjdGl2ZTogXCJ3aW5kb3dzOldpbmRvd0FjdGl2ZVwiLFxuXHRcdFdpbmRvd0NsaWNrQWN0aXZlOiBcIndpbmRvd3M6V2luZG93Q2xpY2tBY3RpdmVcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcIndpbmRvd3M6V2luZG93RnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1VuRnVsbHNjcmVlbjogXCJ3aW5kb3dzOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwid2luZG93czpXaW5kb3dSZXN0b3JlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwid2luZG93czpXaW5kb3dNaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWluaW1pc2U6IFwid2luZG93czpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Q2xvc2U6IFwid2luZG93czpXaW5kb3dDbG9zZVwiLFxuXHRcdFdpbmRvd1NldEZvY3VzOiBcIndpbmRvd3M6V2luZG93U2V0Rm9jdXNcIixcblx0XHRXaW5kb3dLaWxsRm9jdXM6IFwid2luZG93czpXaW5kb3dLaWxsRm9jdXNcIixcblx0XHRXaW5kb3dEcmFnRHJvcDogXCJ3aW5kb3dzOldpbmRvd0RyYWdEcm9wXCIsXG5cdFx0V2luZG93RHJhZ0VudGVyOiBcIndpbmRvd3M6V2luZG93RHJhZ0VudGVyXCIsXG5cdFx0V2luZG93RHJhZ0xlYXZlOiBcIndpbmRvd3M6V2luZG93RHJhZ0xlYXZlXCIsXG5cdFx0V2luZG93RHJhZ092ZXI6IFwid2luZG93czpXaW5kb3dEcmFnT3ZlclwiLFxuXHR9LFxuXHRNYWM6IHtcblx0XHRBcHBsaWNhdGlvbkRpZEJlY29tZUFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUVmZmVjdGl2ZUFwcGVhcmFuY2VcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZUljb246IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlSWNvblwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU2NyZWVuUGFyYW1ldGVyc1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlU3RhdHVzQmFyRnJhbWVcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0Jhck9yaWVudGF0aW9uXCIsXG5cdFx0QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmc6IFwibWFjOkFwcGxpY2F0aW9uRGlkRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25EaWRIaWRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZEhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFJlc2lnbkFjdGl2ZU5vdGlmaWNhdGlvbjogXCJtYWM6QXBwbGljYXRpb25EaWRSZXNpZ25BY3RpdmVOb3RpZmljYXRpb25cIixcblx0XHRBcHBsaWNhdGlvbkRpZFVuaGlkZTogXCJtYWM6QXBwbGljYXRpb25EaWRVbmhpZGVcIixcblx0XHRBcHBsaWNhdGlvbkRpZFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25EaWRVcGRhdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxCZWNvbWVBY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbEJlY29tZUFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEZpbmlzaExhdW5jaGluZzogXCJtYWM6QXBwbGljYXRpb25XaWxsRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsSGlkZTogXCJtYWM6QXBwbGljYXRpb25XaWxsSGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFJlc2lnbkFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVGVybWluYXRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxVbmhpZGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFVuaGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFVwZGF0ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsVXBkYXRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZTogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VUaGVtZSFcIixcblx0XHRBcHBsaWNhdGlvblNob3VsZEhhbmRsZVJlb3BlbjogXCJtYWM6QXBwbGljYXRpb25TaG91bGRIYW5kbGVSZW9wZW4hXCIsXG5cdFx0V2luZG93RGlkQmVjb21lS2V5OiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dEaWRCZWNvbWVNYWluOiBcIm1hYzpXaW5kb3dEaWRCZWNvbWVNYWluXCIsXG5cdFx0V2luZG93RGlkQmVnaW5TaGVldDogXCJtYWM6V2luZG93RGlkQmVnaW5TaGVldFwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUFscGhhOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VBbHBoYVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUJhY2tpbmdMb2NhdGlvbjogXCJtYWM6V2luZG93RGlkQ2hhbmdlQmFja2luZ0xvY2F0aW9uXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQmFja2luZ1Byb3BlcnRpZXM6IFwibWFjOldpbmRvd0RpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT2NjbHVzaW9uU3RhdGU6IFwibWFjOldpbmRvd0RpZENoYW5nZU9jY2x1c2lvblN0YXRlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW46IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnM6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblBhcmFtZXRlcnNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5Qcm9maWxlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2U6IFwibWFjOldpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2VQcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5TcGFjZVByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTaGFyaW5nVHlwZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2hhcmluZ1R5cGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTcGFjZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU3BhY2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUaXRsZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVGl0bGVcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VUb29sYmFyOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VUb29sYmFyXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eTogXCJtYWM6V2luZG93RGlkQ2hhbmdlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd0RpZERlbWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dEaWRFbmRTaGVldDogXCJtYWM6V2luZG93RGlkRW5kU2hlZXRcIixcblx0XHRXaW5kb3dEaWRFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd0RpZEVudGVyRnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dEaWRFeGl0RnVsbFNjcmVlbjogXCJtYWM6V2luZG93RGlkRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEV4aXRWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd0RpZEV4cG9zZTogXCJtYWM6V2luZG93RGlkRXhwb3NlXCIsXG5cdFx0V2luZG93RGlkRm9jdXM6IFwibWFjOldpbmRvd0RpZEZvY3VzXCIsXG5cdFx0V2luZG93RGlkTWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJtYWM6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRPcmRlck9mZlNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd0RpZE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dEaWRSZXNpZ25LZXk6IFwibWFjOldpbmRvd0RpZFJlc2lnbktleVwiLFxuXHRcdFdpbmRvd0RpZFJlc2lnbk1haW46IFwibWFjOldpbmRvd0RpZFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwibWFjOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZTogXCJtYWM6V2luZG93RGlkVXBkYXRlXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd0RpZFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRpdGxlOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVRvb2xiYXJcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVWaXNpYmlsaXR5XCIsXG5cdFx0V2luZG93U2hvdWxkQ2xvc2U6IFwibWFjOldpbmRvd1Nob3VsZENsb3NlIVwiLFxuXHRcdFdpbmRvd1dpbGxCZWNvbWVLZXk6IFwibWFjOldpbmRvd1dpbGxCZWNvbWVLZXlcIixcblx0XHRXaW5kb3dXaWxsQmVjb21lTWFpbjogXCJtYWM6V2luZG93V2lsbEJlY29tZU1haW5cIixcblx0XHRXaW5kb3dXaWxsQmVnaW5TaGVldDogXCJtYWM6V2luZG93V2lsbEJlZ2luU2hlZXRcIixcblx0XHRXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlOiBcIm1hYzpXaW5kb3dXaWxsQ2hhbmdlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93V2lsbENsb3NlOiBcIm1hYzpXaW5kb3dXaWxsQ2xvc2VcIixcblx0XHRXaW5kb3dXaWxsRGVtaW5pYXR1cml6ZTogXCJtYWM6V2luZG93V2lsbERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRW50ZXJGdWxsU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd1dpbGxFbnRlclZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEV4aXRGdWxsU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyOiBcIm1hYzpXaW5kb3dXaWxsRXhpdFZlcnNpb25Ccm93c2VyXCIsXG5cdFx0V2luZG93V2lsbEZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsRm9jdXNcIixcblx0XHRXaW5kb3dXaWxsTWluaWF0dXJpemU6IFwibWFjOldpbmRvd1dpbGxNaW5pYXR1cml6ZVwiLFxuXHRcdFdpbmRvd1dpbGxNb3ZlOiBcIm1hYzpXaW5kb3dXaWxsTW92ZVwiLFxuXHRcdFdpbmRvd1dpbGxPcmRlck9mZlNjcmVlbjogXCJtYWM6V2luZG93V2lsbE9yZGVyT2ZmU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd1dpbGxPcmRlck9uU2NyZWVuXCIsXG5cdFx0V2luZG93V2lsbFJlc2lnbk1haW46IFwibWFjOldpbmRvd1dpbGxSZXNpZ25NYWluXCIsXG5cdFx0V2luZG93V2lsbFJlc2l6ZTogXCJtYWM6V2luZG93V2lsbFJlc2l6ZVwiLFxuXHRcdFdpbmRvd1dpbGxVbmZvY3VzOiBcIm1hYzpXaW5kb3dXaWxsVW5mb2N1c1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVBbHBoYVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3I6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXM6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllc1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVTaGFkb3dcIixcblx0XHRXaW5kb3dXaWxsVXBkYXRlVGl0bGU6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVUb29sYmFyOiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVG9vbGJhclwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVWaXNpYmlsaXR5OiBcIm1hYzpXaW5kb3dXaWxsVXBkYXRlVmlzaWJpbGl0eVwiLFxuXHRcdFdpbmRvd1dpbGxVc2VTdGFuZGFyZEZyYW1lOiBcIm1hYzpXaW5kb3dXaWxsVXNlU3RhbmRhcmRGcmFtZVwiLFxuXHRcdE1lbnVXaWxsT3BlbjogXCJtYWM6TWVudVdpbGxPcGVuXCIsXG5cdFx0TWVudURpZE9wZW46IFwibWFjOk1lbnVEaWRPcGVuXCIsXG5cdFx0TWVudURpZENsb3NlOiBcIm1hYzpNZW51RGlkQ2xvc2VcIixcblx0XHRNZW51V2lsbFNlbmRBY3Rpb246IFwibWFjOk1lbnVXaWxsU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVXaWxsSGlnaGxpZ2h0SXRlbTogXCJtYWM6TWVudVdpbGxIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudURpZEhpZ2hsaWdodEl0ZW06IFwibWFjOk1lbnVEaWRIaWdobGlnaHRJdGVtXCIsXG5cdFx0TWVudVdpbGxEaXNwbGF5SXRlbTogXCJtYWM6TWVudVdpbGxEaXNwbGF5SXRlbVwiLFxuXHRcdE1lbnVEaWREaXNwbGF5SXRlbTogXCJtYWM6TWVudURpZERpc3BsYXlJdGVtXCIsXG5cdFx0TWVudVdpbGxBZGRJdGVtOiBcIm1hYzpNZW51V2lsbEFkZEl0ZW1cIixcblx0XHRNZW51RGlkQWRkSXRlbTogXCJtYWM6TWVudURpZEFkZEl0ZW1cIixcblx0XHRNZW51V2lsbFJlbW92ZUl0ZW06IFwibWFjOk1lbnVXaWxsUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVEaWRSZW1vdmVJdGVtOiBcIm1hYzpNZW51RGlkUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVXaWxsQmVnaW5UcmFja2luZzogXCJtYWM6TWVudVdpbGxCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudURpZEJlZ2luVHJhY2tpbmc6IFwibWFjOk1lbnVEaWRCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxFbmRUcmFja2luZzogXCJtYWM6TWVudVdpbGxFbmRUcmFja2luZ1wiLFxuXHRcdE1lbnVEaWRFbmRUcmFja2luZzogXCJtYWM6TWVudURpZEVuZFRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxVcGRhdGU6IFwibWFjOk1lbnVXaWxsVXBkYXRlXCIsXG5cdFx0TWVudURpZFVwZGF0ZTogXCJtYWM6TWVudURpZFVwZGF0ZVwiLFxuXHRcdE1lbnVXaWxsUG9wVXA6IFwibWFjOk1lbnVXaWxsUG9wVXBcIixcblx0XHRNZW51RGlkUG9wVXA6IFwibWFjOk1lbnVEaWRQb3BVcFwiLFxuXHRcdE1lbnVXaWxsU2VuZEFjdGlvblRvSXRlbTogXCJtYWM6TWVudVdpbGxTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0TWVudURpZFNlbmRBY3Rpb25Ub0l0ZW06IFwibWFjOk1lbnVEaWRTZW5kQWN0aW9uVG9JdGVtXCIsXG5cdFx0V2ViVmlld0RpZFN0YXJ0UHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkU3RhcnRQcm92aXNpb25hbE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkUmVjZWl2ZVNlcnZlclJlZGlyZWN0Rm9yUHJvdmlzaW9uYWxOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZEZpbmlzaE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RpZENvbW1pdE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRDb21taXROYXZpZ2F0aW9uXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZFwiLFxuXHRcdFdpbmRvd0ZpbGVEcmFnZ2luZ1BlcmZvcm1lZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nUGVyZm9ybWVkXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRXhpdGVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdFeGl0ZWRcIixcblx0fSxcblx0TGludXg6IHtcblx0XHRTeXN0ZW1UaGVtZUNoYW5nZWQ6IFwibGludXg6U3lzdGVtVGhlbWVDaGFuZ2VkXCIsXG5cdFx0V2luZG93TG9hZENoYW5nZWQ6IFwibGludXg6V2luZG93TG9hZENoYW5nZWRcIixcblx0XHRXaW5kb3dEZWxldGVFdmVudDogXCJsaW51eDpXaW5kb3dEZWxldGVFdmVudFwiLFxuXHRcdFdpbmRvd0ZvY3VzSW46IFwibGludXg6V2luZG93Rm9jdXNJblwiLFxuXHRcdFdpbmRvd0ZvY3VzT3V0OiBcImxpbnV4OldpbmRvd0ZvY3VzT3V0XCIsXG5cdFx0QXBwbGljYXRpb25TdGFydHVwOiBcImxpbnV4OkFwcGxpY2F0aW9uU3RhcnR1cFwiLFxuXHR9LFxuXHRDb21tb246IHtcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwiY29tbW9uOkFwcGxpY2F0aW9uU3RhcnRlZFwiLFxuXHRcdFdpbmRvd01heGltaXNlOiBcImNvbW1vbjpXaW5kb3dNYXhpbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWF4aW1pc2U6IFwiY29tbW9uOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcImNvbW1vbjpXaW5kb3dGdWxsc2NyZWVuXCIsXG5cdFx0V2luZG93VW5GdWxsc2NyZWVuOiBcImNvbW1vbjpXaW5kb3dVbkZ1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dSZXN0b3JlOiBcImNvbW1vbjpXaW5kb3dSZXN0b3JlXCIsXG5cdFx0V2luZG93TWluaW1pc2U6IFwiY29tbW9uOldpbmRvd01pbmltaXNlXCIsXG5cdFx0V2luZG93VW5NaW5pbWlzZTogXCJjb21tb246V2luZG93VW5NaW5pbWlzZVwiLFxuXHRcdFdpbmRvd0Nsb3Npbmc6IFwiY29tbW9uOldpbmRvd0Nsb3NpbmdcIixcblx0XHRXaW5kb3dab29tOiBcImNvbW1vbjpXaW5kb3dab29tXCIsXG5cdFx0V2luZG93Wm9vbUluOiBcImNvbW1vbjpXaW5kb3dab29tSW5cIixcblx0XHRXaW5kb3dab29tT3V0OiBcImNvbW1vbjpXaW5kb3dab29tT3V0XCIsXG5cdFx0V2luZG93Wm9vbVJlc2V0OiBcImNvbW1vbjpXaW5kb3dab29tUmVzZXRcIixcblx0XHRXaW5kb3dGb2N1czogXCJjb21tb246V2luZG93Rm9jdXNcIixcblx0XHRXaW5kb3dMb3N0Rm9jdXM6IFwiY29tbW9uOldpbmRvd0xvc3RGb2N1c1wiLFxuXHRcdFdpbmRvd1Nob3c6IFwiY29tbW9uOldpbmRvd1Nob3dcIixcblx0XHRXaW5kb3dIaWRlOiBcImNvbW1vbjpXaW5kb3dIaWRlXCIsXG5cdFx0V2luZG93RFBJQ2hhbmdlZDogXCJjb21tb246V2luZG93RFBJQ2hhbmdlZFwiLFxuXHRcdFdpbmRvd0ZpbGVzRHJvcHBlZDogXCJjb21tb246V2luZG93RmlsZXNEcm9wcGVkXCIsXG5cdFx0V2luZG93UnVudGltZVJlYWR5OiBcImNvbW1vbjpXaW5kb3dSdW50aW1lUmVhZHlcIixcblx0XHRUaGVtZUNoYW5nZWQ6IFwiY29tbW9uOlRoZW1lQ2hhbmdlZFwiLFxuXHR9LFxufTtcbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IE9wZW5GaWxlRGlhbG9nT3B0aW9uc1xuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ2hvb3NlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjaG9zZW4uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DaG9vc2VGaWxlc10gLSBJbmRpY2F0ZXMgaWYgZmlsZXMgY2FuIGJlIGNob3Nlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNyZWF0ZURpcmVjdG9yaWVzXSAtIEluZGljYXRlcyBpZiBkaXJlY3RvcmllcyBjYW4gYmUgY3JlYXRlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1Nob3dIaWRkZW5GaWxlc10gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGZpbGVzIHNob3VsZCBiZSBzaG93bi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1Jlc29sdmVzQWxpYXNlc10gLSBJbmRpY2F0ZXMgaWYgYWxpYXNlcyBzaG91bGQgYmUgcmVzb2x2ZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtBbGxvd3NNdWx0aXBsZVNlbGVjdGlvbl0gLSBJbmRpY2F0ZXMgaWYgbXVsdGlwbGUgc2VsZWN0aW9uIGlzIGFsbG93ZWQuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtIaWRlRXh0ZW5zaW9uXSAtIEluZGljYXRlcyBpZiB0aGUgZXh0ZW5zaW9uIHNob3VsZCBiZSBoaWRkZW4uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5TZWxlY3RIaWRkZW5FeHRlbnNpb25dIC0gSW5kaWNhdGVzIGlmIGhpZGRlbiBleHRlbnNpb25zIGNhbiBiZSBzZWxlY3RlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW1RyZWF0c0ZpbGVQYWNrYWdlc0FzRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGZpbGUgcGFja2FnZXMgc2hvdWxkIGJlIHRyZWF0ZWQgYXMgZGlyZWN0b3JpZXMuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtBbGxvd3NPdGhlckZpbGV0eXBlc10gLSBJbmRpY2F0ZXMgaWYgb3RoZXIgZmlsZSB0eXBlcyBhcmUgYWxsb3dlZC5cbiAqIEBwcm9wZXJ0eSB7RmlsZUZpbHRlcltdfSBbRmlsdGVyc10gLSBBcnJheSBvZiBmaWxlIGZpbHRlcnMuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW1RpdGxlXSAtIFRpdGxlIG9mIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW01lc3NhZ2VdIC0gTWVzc2FnZSB0byBzaG93IGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0J1dHRvblRleHRdIC0gVGV4dCB0byBkaXNwbGF5IG9uIHRoZSBidXR0b24uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0RpcmVjdG9yeV0gLSBEaXJlY3RvcnkgdG8gb3BlbiBpbiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbRGV0YWNoZWRdIC0gSW5kaWNhdGVzIGlmIHRoZSBkaWFsb2cgc2hvdWxkIGFwcGVhciBkZXRhY2hlZCBmcm9tIHRoZSBtYWluIHdpbmRvdy5cbiAqL1xuXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gU2F2ZUZpbGVEaWFsb2dPcHRpb25zXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0ZpbGVuYW1lXSAtIERlZmF1bHQgZmlsZW5hbWUgdG8gdXNlIGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtDYW5DaG9vc2VEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZGlyZWN0b3JpZXMgY2FuIGJlIGNob3Nlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhbkNob29zZUZpbGVzXSAtIEluZGljYXRlcyBpZiBmaWxlcyBjYW4gYmUgY2hvc2VuLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbQ2FuQ3JlYXRlRGlyZWN0b3JpZXNdIC0gSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjcmVhdGVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbU2hvd0hpZGRlbkZpbGVzXSAtIEluZGljYXRlcyBpZiBoaWRkZW4gZmlsZXMgc2hvdWxkIGJlIHNob3duLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbUmVzb2x2ZXNBbGlhc2VzXSAtIEluZGljYXRlcyBpZiBhbGlhc2VzIHNob3VsZCBiZSByZXNvbHZlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c011bHRpcGxlU2VsZWN0aW9uXSAtIEluZGljYXRlcyBpZiBtdWx0aXBsZSBzZWxlY3Rpb24gaXMgYWxsb3dlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0hpZGVFeHRlbnNpb25dIC0gSW5kaWNhdGVzIGlmIHRoZSBleHRlbnNpb24gc2hvdWxkIGJlIGhpZGRlbi5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0NhblNlbGVjdEhpZGRlbkV4dGVuc2lvbl0gLSBJbmRpY2F0ZXMgaWYgaGlkZGVuIGV4dGVuc2lvbnMgY2FuIGJlIHNlbGVjdGVkLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbVHJlYXRzRmlsZVBhY2thZ2VzQXNEaXJlY3Rvcmllc10gLSBJbmRpY2F0ZXMgaWYgZmlsZSBwYWNrYWdlcyBzaG91bGQgYmUgdHJlYXRlZCBhcyBkaXJlY3Rvcmllcy5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0FsbG93c090aGVyRmlsZXR5cGVzXSAtIEluZGljYXRlcyBpZiBvdGhlciBmaWxlIHR5cGVzIGFyZSBhbGxvd2VkLlxuICogQHByb3BlcnR5IHtGaWxlRmlsdGVyW119IFtGaWx0ZXJzXSAtIEFycmF5IG9mIGZpbGUgZmlsdGVycy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGl0bGUgb2YgdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbTWVzc2FnZV0gLSBNZXNzYWdlIHRvIHNob3cgaW4gdGhlIGRpYWxvZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbQnV0dG9uVGV4dF0gLSBUZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbRGlyZWN0b3J5XSAtIERpcmVjdG9yeSB0byBvcGVuIGluIHRoZSBkaWFsb2cuXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtEZXRhY2hlZF0gLSBJbmRpY2F0ZXMgaWYgdGhlIGRpYWxvZyBzaG91bGQgYXBwZWFyIGRldGFjaGVkIGZyb20gdGhlIG1haW4gd2luZG93LlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gTWVzc2FnZURpYWxvZ09wdGlvbnNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbVGl0bGVdIC0gVGhlIHRpdGxlIG9mIHRoZSBkaWFsb2cgd2luZG93LlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtNZXNzYWdlXSAtIFRoZSBtYWluIG1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtCdXR0b25bXX0gW0J1dHRvbnNdIC0gQXJyYXkgb2YgYnV0dG9uIG9wdGlvbnMgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbRGV0YWNoZWRdIC0gVHJ1ZSBpZiB0aGUgZGlhbG9nIHNob3VsZCBhcHBlYXIgZGV0YWNoZWQgZnJvbSB0aGUgbWFpbiB3aW5kb3cgKGlmIGFwcGxpY2FibGUpLlxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gQnV0dG9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0xhYmVsXSAtIFRleHQgdGhhdCBhcHBlYXJzIHdpdGhpbiB0aGUgYnV0dG9uLlxuICogQHByb3BlcnR5IHtib29sZWFufSBbSXNDYW5jZWxdIC0gVHJ1ZSBpZiB0aGUgYnV0dG9uIHNob3VsZCBjYW5jZWwgYW4gb3BlcmF0aW9uIHdoZW4gY2xpY2tlZC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW0lzRGVmYXVsdF0gLSBUcnVlIGlmIHRoZSBidXR0b24gc2hvdWxkIGJlIHRoZSBkZWZhdWx0IGFjdGlvbiB3aGVuIHRoZSB1c2VyIHByZXNzZXMgZW50ZXIuXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBGaWxlRmlsdGVyXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW0Rpc3BsYXlOYW1lXSAtIERpc3BsYXkgbmFtZSBmb3IgdGhlIGZpbHRlciwgaXQgY291bGQgYmUgXCJUZXh0IEZpbGVzXCIsIFwiSW1hZ2VzXCIgZXRjLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtQYXR0ZXJuXSAtIFBhdHRlcm4gdG8gbWF0Y2ggZm9yIHRoZSBmaWx0ZXIsIGUuZy4gXCIqLnR4dDsqLm1kXCIgZm9yIHRleHQgbWFya2Rvd24gZmlsZXMuXG4gKi9cblxuLy8gc2V0dXBcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xud2luZG93Ll93YWlscy5kaWFsb2dFcnJvckNhbGxiYWNrID0gZGlhbG9nRXJyb3JDYWxsYmFjaztcbndpbmRvdy5fd2FpbHMuZGlhbG9nUmVzdWx0Q2FsbGJhY2sgPSBkaWFsb2dSZXN1bHRDYWxsYmFjaztcblxuaW1wb3J0IHtuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lc30gZnJvbSBcIi4vcnVudGltZVwiO1xuXG5pbXBvcnQgeyBuYW5vaWQgfSBmcm9tICduYW5vaWQvbm9uLXNlY3VyZSc7XG5cbi8vIERlZmluZSBjb25zdGFudHMgZnJvbSB0aGUgYG1ldGhvZHNgIG9iamVjdCBpbiBUaXRsZSBDYXNlXG5jb25zdCBEaWFsb2dJbmZvID0gMDtcbmNvbnN0IERpYWxvZ1dhcm5pbmcgPSAxO1xuY29uc3QgRGlhbG9nRXJyb3IgPSAyO1xuY29uc3QgRGlhbG9nUXVlc3Rpb24gPSAzO1xuY29uc3QgRGlhbG9nT3BlbkZpbGUgPSA0O1xuY29uc3QgRGlhbG9nU2F2ZUZpbGUgPSA1O1xuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcldpdGhJRChvYmplY3ROYW1lcy5EaWFsb2csICcnKTtcbmNvbnN0IGRpYWxvZ1Jlc3BvbnNlcyA9IG5ldyBNYXAoKTtcblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgaWQgdGhhdCBpcyBub3QgcHJlc2VudCBpbiBkaWFsb2dSZXNwb25zZXMuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSB1bmlxdWUgaWRcbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVJRCgpIHtcbiAgICBsZXQgcmVzdWx0O1xuICAgIGRvIHtcbiAgICAgICAgcmVzdWx0ID0gbmFub2lkKCk7XG4gICAgfSB3aGlsZSAoZGlhbG9nUmVzcG9uc2VzLmhhcyhyZXN1bHQpKTtcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIFNob3dzIGEgZGlhbG9nIG9mIHNwZWNpZmllZCB0eXBlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG4gKiBAcGFyYW0ge251bWJlcn0gdHlwZSAtIHR5cGUgb2YgZGlhbG9nXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfE9wZW5GaWxlRGlhbG9nT3B0aW9uc3xTYXZlRmlsZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBvcHRpb25zIGZvciB0aGUgZGlhbG9nXG4gKiBAcmV0dXJucyB7UHJvbWlzZX0gcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggcmVzdWx0IG9mIGRpYWxvZ1xuICovXG5mdW5jdGlvbiBkaWFsb2codHlwZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgaWQgPSBnZW5lcmF0ZUlEKCk7XG4gICAgb3B0aW9uc1tcImRpYWxvZy1pZFwiXSA9IGlkO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGRpYWxvZ1Jlc3BvbnNlcy5zZXQoaWQsIHtyZXNvbHZlLCByZWplY3R9KTtcbiAgICAgICAgY2FsbCh0eXBlLCBvcHRpb25zKS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICBkaWFsb2dSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogSGFuZGxlcyB0aGUgY2FsbGJhY2sgZnJvbSBhIGRpYWxvZy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBUaGUgSUQgb2YgdGhlIGRpYWxvZyByZXNwb25zZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRhIC0gVGhlIGRhdGEgcmVjZWl2ZWQgZnJvbSB0aGUgZGlhbG9nLlxuICogQHBhcmFtIHtib29sZWFufSBpc0pTT04gLSBGbGFnIGluZGljYXRpbmcgd2hldGhlciB0aGUgZGF0YSBpcyBpbiBKU09OIGZvcm1hdC5cbiAqXG4gKiBAcmV0dXJuIHt1bmRlZmluZWR9XG4gKi9cbmZ1bmN0aW9uIGRpYWxvZ1Jlc3VsdENhbGxiYWNrKGlkLCBkYXRhLCBpc0pTT04pIHtcbiAgICBsZXQgcCA9IGRpYWxvZ1Jlc3BvbnNlcy5nZXQoaWQpO1xuICAgIGlmIChwKSB7XG4gICAgICAgIGlmIChpc0pTT04pIHtcbiAgICAgICAgICAgIHAucmVzb2x2ZShKU09OLnBhcnNlKGRhdGEpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHAucmVzb2x2ZShkYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBkaWFsb2dSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICB9XG59XG5cbi8qKlxuICogQ2FsbGJhY2sgZnVuY3Rpb24gZm9yIGhhbmRsaW5nIGVycm9ycyBpbiBkaWFsb2cuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gVGhlIGlkIG9mIHRoZSBkaWFsb2cgcmVzcG9uc2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIFRoZSBlcnJvciBtZXNzYWdlLlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGRpYWxvZ0Vycm9yQ2FsbGJhY2soaWQsIG1lc3NhZ2UpIHtcbiAgICBsZXQgcCA9IGRpYWxvZ1Jlc3BvbnNlcy5nZXQoaWQpO1xuICAgIGlmIChwKSB7XG4gICAgICAgIHAucmVqZWN0KG1lc3NhZ2UpO1xuICAgICAgICBkaWFsb2dSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICB9XG59XG5cblxuLy8gUmVwbGFjZSBgbWV0aG9kc2Agd2l0aCBjb25zdGFudHMgaW4gVGl0bGUgQ2FzZVxuXG4vKipcbiAqIEBwYXJhbSB7TWVzc2FnZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gLSBUaGUgbGFiZWwgb2YgdGhlIGJ1dHRvbiBwcmVzc2VkXG4gKi9cbmV4cG9ydCBjb25zdCBJbmZvID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dJbmZvLCBvcHRpb25zKTtcblxuLyoqXG4gKiBAcGFyYW0ge01lc3NhZ2VEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IC0gVGhlIGxhYmVsIG9mIHRoZSBidXR0b24gcHJlc3NlZFxuICovXG5leHBvcnQgY29uc3QgV2FybmluZyA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nV2FybmluZywgb3B0aW9ucyk7XG5cbi8qKlxuICogQHBhcmFtIHtNZXNzYWdlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcbiAqL1xuZXhwb3J0IGNvbnN0IEVycm9yID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dFcnJvciwgb3B0aW9ucyk7XG5cbi8qKlxuICogQHBhcmFtIHtNZXNzYWdlRGlhbG9nT3B0aW9uc30gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSAtIFRoZSBsYWJlbCBvZiB0aGUgYnV0dG9uIHByZXNzZWRcbiAqL1xuZXhwb3J0IGNvbnN0IFF1ZXN0aW9uID0gKG9wdGlvbnMpID0+IGRpYWxvZyhEaWFsb2dRdWVzdGlvbiwgb3B0aW9ucyk7XG5cbi8qKlxuICogQHBhcmFtIHtPcGVuRmlsZURpYWxvZ09wdGlvbnN9IG9wdGlvbnMgLSBEaWFsb2cgb3B0aW9uc1xuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nW118c3RyaW5nPn0gUmV0dXJucyBzZWxlY3RlZCBmaWxlIG9yIGxpc3Qgb2YgZmlsZXMuIFJldHVybnMgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaXMgc2VsZWN0ZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBPcGVuRmlsZSA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nT3BlbkZpbGUsIG9wdGlvbnMpO1xuXG4vKipcbiAqIEBwYXJhbSB7U2F2ZUZpbGVEaWFsb2dPcHRpb25zfSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZz59IFJldHVybnMgdGhlIHNlbGVjdGVkIGZpbGUuIFJldHVybnMgYmxhbmsgc3RyaW5nIGlmIG5vIGZpbGUgaXMgc2VsZWN0ZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBTYXZlRmlsZSA9IChvcHRpb25zKSA9PiBkaWFsb2coRGlhbG9nU2F2ZUZpbGUsIG9wdGlvbnMpO1xuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQgeyBuZXdSdW50aW1lQ2FsbGVyV2l0aElELCBvYmplY3ROYW1lcyB9IGZyb20gXCIuL3J1bnRpbWVcIjtcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gJ25hbm9pZC9ub24tc2VjdXJlJztcblxuLy8gU2V0dXBcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xud2luZG93Ll93YWlscy5jYWxsUmVzdWx0SGFuZGxlciA9IHJlc3VsdEhhbmRsZXI7XG53aW5kb3cuX3dhaWxzLmNhbGxFcnJvckhhbmRsZXIgPSBlcnJvckhhbmRsZXI7XG5cblxuY29uc3QgQ2FsbEJpbmRpbmcgPSAwO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXJXaXRoSUQob2JqZWN0TmFtZXMuQ2FsbCwgJycpO1xubGV0IGNhbGxSZXNwb25zZXMgPSBuZXcgTWFwKCk7XG5cbi8qKlxuICogR2VuZXJhdGVzIGEgdW5pcXVlIElEIHVzaW5nIHRoZSBuYW5vaWQgbGlicmFyeS5cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IC0gQSB1bmlxdWUgSUQgdGhhdCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgY2FsbFJlc3BvbnNlcyBzZXQuXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlSUQoKSB7XG4gICAgbGV0IHJlc3VsdDtcbiAgICBkbyB7XG4gICAgICAgIHJlc3VsdCA9IG5hbm9pZCgpO1xuICAgIH0gd2hpbGUgKGNhbGxSZXNwb25zZXMuaGFzKHJlc3VsdCkpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogSGFuZGxlcyB0aGUgcmVzdWx0IG9mIGEgY2FsbCByZXF1ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIFRoZSBpZCBvZiB0aGUgcmVxdWVzdCB0byBoYW5kbGUgdGhlIHJlc3VsdCBmb3IuXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YSAtIFRoZSByZXN1bHQgZGF0YSBvZiB0aGUgcmVxdWVzdC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNKU09OIC0gSW5kaWNhdGVzIHdoZXRoZXIgdGhlIGRhdGEgaXMgSlNPTiBvciBub3QuXG4gKlxuICogQHJldHVybiB7dW5kZWZpbmVkfSAtIFRoaXMgbWV0aG9kIGRvZXMgbm90IHJldHVybiBhbnkgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIHJlc3VsdEhhbmRsZXIoaWQsIGRhdGEsIGlzSlNPTikge1xuICAgIGNvbnN0IHByb21pc2VIYW5kbGVyID0gZ2V0QW5kRGVsZXRlUmVzcG9uc2UoaWQpO1xuICAgIGlmIChwcm9taXNlSGFuZGxlcikge1xuICAgICAgICBwcm9taXNlSGFuZGxlci5yZXNvbHZlKGlzSlNPTiA/IEpTT04ucGFyc2UoZGF0YSkgOiBkYXRhKTtcbiAgICB9XG59XG5cbi8qKlxuICogSGFuZGxlcyB0aGUgZXJyb3IgZnJvbSBhIGNhbGwgcmVxdWVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBUaGUgaWQgb2YgdGhlIHByb21pc2UgaGFuZGxlci5cbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UgdG8gcmVqZWN0IHRoZSBwcm9taXNlIGhhbmRsZXIgd2l0aC5cbiAqXG4gKiBAcmV0dXJuIHt2b2lkfVxuICovXG5mdW5jdGlvbiBlcnJvckhhbmRsZXIoaWQsIG1lc3NhZ2UpIHtcbiAgICBjb25zdCBwcm9taXNlSGFuZGxlciA9IGdldEFuZERlbGV0ZVJlc3BvbnNlKGlkKTtcbiAgICBpZiAocHJvbWlzZUhhbmRsZXIpIHtcbiAgICAgICAgcHJvbWlzZUhhbmRsZXIucmVqZWN0KG1lc3NhZ2UpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZXRyaWV2ZXMgYW5kIHJlbW92ZXMgdGhlIHJlc3BvbnNlIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gSUQgZnJvbSB0aGUgY2FsbFJlc3BvbnNlcyBtYXAuXG4gKlxuICogQHBhcmFtIHthbnl9IGlkIC0gVGhlIElEIG9mIHRoZSByZXNwb25zZSB0byBiZSByZXRyaWV2ZWQgYW5kIHJlbW92ZWQuXG4gKlxuICogQHJldHVybnMge2FueX0gVGhlIHJlc3BvbnNlIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIElELlxuICovXG5mdW5jdGlvbiBnZXRBbmREZWxldGVSZXNwb25zZShpZCkge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gY2FsbFJlc3BvbnNlcy5nZXQoaWQpO1xuICAgIGNhbGxSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICByZXR1cm4gcmVzcG9uc2U7XG59XG5cbi8qKlxuICogRXhlY3V0ZXMgYSBjYWxsIHVzaW5nIHRoZSBwcm92aWRlZCB0eXBlIGFuZCBvcHRpb25zLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gdHlwZSAtIFRoZSB0eXBlIG9mIGNhbGwgdG8gZXhlY3V0ZS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gLSBBZGRpdGlvbmFsIG9wdGlvbnMgZm9yIHRoZSBjYWxsLlxuICogQHJldHVybiB7UHJvbWlzZX0gLSBBIHByb21pc2UgdGhhdCB3aWxsIGJlIHJlc29sdmVkIG9yIHJlamVjdGVkIGJhc2VkIG9uIHRoZSByZXN1bHQgb2YgdGhlIGNhbGwuXG4gKi9cbmZ1bmN0aW9uIGNhbGxCaW5kaW5nKHR5cGUsIG9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGNvbnN0IGlkID0gZ2VuZXJhdGVJRCgpO1xuICAgICAgICBvcHRpb25zW1wiY2FsbC1pZFwiXSA9IGlkO1xuICAgICAgICBjYWxsUmVzcG9uc2VzLnNldChpZCwgeyByZXNvbHZlLCByZWplY3QgfSk7XG4gICAgICAgIGNhbGwodHlwZSwgb3B0aW9ucykuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgY2FsbFJlc3BvbnNlcy5kZWxldGUoaWQpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBDYWxsIG1ldGhvZC5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIFRoZSBvcHRpb25zIGZvciB0aGUgbWV0aG9kLlxuICogQHJldHVybnMge09iamVjdH0gLSBUaGUgcmVzdWx0IG9mIHRoZSBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQ2FsbChvcHRpb25zKSB7XG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCBvcHRpb25zKTtcbn1cblxuLyoqXG4gKiBFeGVjdXRlcyBhIG1ldGhvZCBieSBuYW1lLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIG1ldGhvZCBpbiB0aGUgZm9ybWF0ICdwYWNrYWdlLnN0cnVjdC5tZXRob2QnLlxuICogQHBhcmFtIHsuLi4qfSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIG5hbWUgaXMgbm90IGEgc3RyaW5nIG9yIGlzIG5vdCBpbiB0aGUgY29ycmVjdCBmb3JtYXQuXG4gKiBAcmV0dXJucyB7Kn0gVGhlIHJlc3VsdCBvZiB0aGUgbWV0aG9kIGV4ZWN1dGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEJ5TmFtZShuYW1lLCAuLi5hcmdzKSB7XG4gICAgaWYgKHR5cGVvZiBuYW1lICE9PSBcInN0cmluZ1wiIHx8IG5hbWUuc3BsaXQoXCIuXCIpLmxlbmd0aCAhPT0gMykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYWxsQnlOYW1lIHJlcXVpcmVzIGEgc3RyaW5nIGluIHRoZSBmb3JtYXQgJ3BhY2thZ2Uuc3RydWN0Lm1ldGhvZCdcIik7XG4gICAgfVxuICAgIGxldCBbcGFja2FnZU5hbWUsIHN0cnVjdE5hbWUsIG1ldGhvZE5hbWVdID0gbmFtZS5zcGxpdChcIi5cIik7XG4gICAgcmV0dXJuIGNhbGxCaW5kaW5nKENhbGxCaW5kaW5nLCB7XG4gICAgICAgIHBhY2thZ2VOYW1lLFxuICAgICAgICBzdHJ1Y3ROYW1lLFxuICAgICAgICBtZXRob2ROYW1lLFxuICAgICAgICBhcmdzXG4gICAgfSk7XG59XG5cbi8qKlxuICogQ2FsbHMgYSBtZXRob2QgYnkgaXRzIElEIHdpdGggdGhlIHNwZWNpZmllZCBhcmd1bWVudHMuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IG1ldGhvZElEIC0gVGhlIElEIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqIEBwYXJhbSB7Li4uKn0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxuICogQHJldHVybiB7Kn0gLSBUaGUgcmVzdWx0IG9mIHRoZSBtZXRob2QgY2FsbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEJ5SUQobWV0aG9kSUQsIC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gY2FsbEJpbmRpbmcoQ2FsbEJpbmRpbmcsIHtcbiAgICAgICAgbWV0aG9kSUQsXG4gICAgICAgIGFyZ3NcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBDYWxscyBhIG1ldGhvZCBvbiBhIHBsdWdpbi5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcGx1Z2luTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwbHVnaW4uXG4gKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqIEBwYXJhbSB7Li4uKn0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxuICogQHJldHVybnMgeyp9IC0gVGhlIHJlc3VsdCBvZiB0aGUgbWV0aG9kIGNhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBQbHVnaW4ocGx1Z2luTmFtZSwgbWV0aG9kTmFtZSwgLi4uYXJncykge1xuICAgIHJldHVybiBjYWxsQmluZGluZyhDYWxsQmluZGluZywge1xuICAgICAgICBwYWNrYWdlTmFtZTogXCJ3YWlscy1wbHVnaW5zXCIsXG4gICAgICAgIHN0cnVjdE5hbWU6IHBsdWdpbk5hbWUsXG4gICAgICAgIG1ldGhvZE5hbWUsXG4gICAgICAgIGFyZ3NcbiAgICB9KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHtkZWJ1Z0xvZ30gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2xvZ1wiO1xuXG53aW5kb3cuX3dhaWxzID0gd2luZG93Ll93YWlscyB8fCB7fTtcblxuaW1wb3J0ICogYXMgQXBwbGljYXRpb24gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2FwcGxpY2F0aW9uXCI7XG5pbXBvcnQgKiBhcyBCcm93c2VyIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9icm93c2VyXCI7XG5pbXBvcnQgKiBhcyBDbGlwYm9hcmQgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NsaXBib2FyZFwiO1xuaW1wb3J0ICogYXMgQ29udGV4dE1lbnUgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NvbnRleHRtZW51XCI7XG5pbXBvcnQgKiBhcyBEcmFnIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyYy9kcmFnXCI7XG5pbXBvcnQgKiBhcyBGbGFncyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3NcIjtcbmltcG9ydCAqIGFzIFNjcmVlbnMgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3NjcmVlbnNcIjtcbmltcG9ydCAqIGFzIFN5c3RlbSBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvc3lzdGVtXCI7XG5pbXBvcnQgKiBhcyBXaW5kb3cgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dpbmRvd1wiO1xuaW1wb3J0ICogYXMgV01MIGZyb20gJy4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dtbCc7XG5pbXBvcnQgKiBhcyBFdmVudHMgZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2V2ZW50c1wiO1xuaW1wb3J0ICogYXMgRGlhbG9ncyBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvZGlhbG9nc1wiO1xuaW1wb3J0ICogYXMgQ2FsbCBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvY2FsbHNcIjtcbmltcG9ydCB7aW52b2tlfSBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvc3lzdGVtXCI7XG5cbi8qKipcbiBUaGlzIHRlY2huaXF1ZSBmb3IgcHJvcGVyIGxvYWQgZGV0ZWN0aW9uIGlzIHRha2VuIGZyb20gSFRNWDpcblxuIEJTRCAyLUNsYXVzZSBMaWNlbnNlXG5cbiBDb3B5cmlnaHQgKGMpIDIwMjAsIEJpZyBTa3kgU29mdHdhcmVcbiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG4gUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0XG4gbW9kaWZpY2F0aW9uLCBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG5cbiAxLiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsIHRoaXNcbiBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cblxuIDIuIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyIGluIHRoZSBkb2N1bWVudGF0aW9uXG4gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG5cbiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIlxuIEFORCBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEVcbiBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkVcbiBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFXG4gRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUxcbiBEQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUlxuIFNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSXG4gQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUIExJQUJJTElUWSxcbiBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRVxuIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG5cbiAqKiovXG5cbndpbmRvdy5fd2FpbHMuaW52b2tlPWludm9rZTtcblxud2luZG93LndhaWxzID0gd2luZG93LndhaWxzIHx8IHt9O1xud2luZG93LndhaWxzLkFwcGxpY2F0aW9uID0gQXBwbGljYXRpb247XG53aW5kb3cud2FpbHMuQnJvd3NlciA9IEJyb3dzZXI7XG53aW5kb3cud2FpbHMuQ2FsbCA9IENhbGw7XG53aW5kb3cud2FpbHMuQ2xpcGJvYXJkID0gQ2xpcGJvYXJkO1xud2luZG93LndhaWxzLkRpYWxvZ3MgPSBEaWFsb2dzO1xud2luZG93LndhaWxzLkV2ZW50cyA9IEV2ZW50cztcbndpbmRvdy53YWlscy5GbGFncyA9IEZsYWdzO1xud2luZG93LndhaWxzLlNjcmVlbnMgPSBTY3JlZW5zO1xud2luZG93LndhaWxzLlN5c3RlbSA9IFN5c3RlbTtcbndpbmRvdy53YWlscy5XaW5kb3cgPSBXaW5kb3c7XG53aW5kb3cud2FpbHMuV01MID0gV01MO1xuXG5cbmxldCBpc1JlYWR5ID0gZmFsc2VcbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCBmdW5jdGlvbigpIHtcbiAgICBpc1JlYWR5ID0gdHJ1ZVxuICAgIHdpbmRvdy5fd2FpbHMuaW52b2tlKCd3YWlsczpydW50aW1lOnJlYWR5Jyk7XG4gICAgaWYoREVCVUcpIHtcbiAgICAgICAgZGVidWdMb2coXCJXYWlscyBSdW50aW1lIExvYWRlZFwiKTtcbiAgICB9XG59KVxuXG5mdW5jdGlvbiB3aGVuUmVhZHkoZm4pIHtcbiAgICBpZiAoaXNSZWFkeSB8fCBkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnY29tcGxldGUnKSB7XG4gICAgICAgIGZuKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGZuKTtcbiAgICB9XG59XG5cbndoZW5SZWFkeSgoKSA9PiB7XG4gICAgV01MLlJlbG9hZCgpO1xufSk7XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7OztBQUtPLFdBQVMsU0FBUyxTQUFTO0FBRTlCLFlBQVE7QUFBQSxNQUNKLGtCQUFrQixVQUFVO0FBQUEsTUFDNUI7QUFBQSxNQUNBO0FBQUEsSUFDSjtBQUFBLEVBQ0o7OztBQ1pBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7O0FDQUEsTUFBSSxjQUNGO0FBV0ssTUFBSSxTQUFTLENBQUNBLFFBQU8sT0FBTztBQUNqQyxRQUFJLEtBQUs7QUFDVCxRQUFJLElBQUlBO0FBQ1IsV0FBTyxLQUFLO0FBQ1YsWUFBTSxZQUFhLEtBQUssT0FBTyxJQUFJLEtBQU0sQ0FBQztBQUFBLElBQzVDO0FBQ0EsV0FBTztBQUFBLEVBQ1Q7OztBQ05BLE1BQU0sYUFBYSxPQUFPLFNBQVMsU0FBUztBQUdyQyxNQUFNLGNBQWM7QUFBQSxJQUN2QixNQUFNO0FBQUEsSUFDTixXQUFXO0FBQUEsSUFDWCxhQUFhO0FBQUEsSUFDYixRQUFRO0FBQUEsSUFDUixhQUFhO0FBQUEsSUFDYixRQUFRO0FBQUEsSUFDUixRQUFRO0FBQUEsSUFDUixTQUFT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QUFvQztBQUFBLE1BQ3BDLCtCQUErQjtBQUFBLE1BQy9CLDZCQUE2QjtBQUFBLE1BQzdCLHVCQUF1QjtBQUFBLE1BQ3ZCLGlDQUFpQztBQUFBLE1BQ2pDLDhCQUE4QjtBQUFBLE1BQzlCLDRCQUE0QjtBQUFBLE1BQzVCLHNDQUFzQztBQUFBLE1BQ3RDLDRCQUE0QjtBQUFBLE1BQzVCLHNCQUFzQjtBQUFBLE1BQ3RCLGtDQUFrQztBQUFBLE1BQ2xDLHNCQUFzQjtBQUFBLE1BQ3RCLHdCQUF3QjtBQUFBLE1BQ3hCLDJCQUEyQjtBQUFBLE1BQzNCLHdCQUF3QjtBQUFBLE1BQ3hCLG1CQUFtQjtBQUFBLE1BQ25CLDBCQUEwQjtBQUFBLE1BQzFCLDhCQUE4QjtBQUFBLE1BQzlCLHlCQUF5QjtBQUFBLE1BQ3pCLDZCQUE2QjtBQUFBLE1BQzdCLGlCQUFpQjtBQUFBLE1BQ2pCLGdCQUFnQjtBQUFBLE1BQ2hCLHNCQUFzQjtBQUFBLE1BQ3RCLGVBQWU7QUFBQSxNQUNmLHlCQUF5QjtBQUFBLE1BQ3pCLHdCQUF3QjtBQUFBLE1BQ3hCLG9CQUFvQjtBQUFBLE1BQ3BCLHFCQUFxQjtBQUFBLE1BQ3JCLGlCQUFpQjtBQUFBLE1BQ2pCLGlCQUFpQjtBQUFBLE1BQ2pCLHNCQUFzQjtBQUFBLE1BQ3RCLG1DQUFtQztBQUFBLE1BQ25DLHFDQUFxQztBQUFBLE1BQ3JDLHVCQUF1QjtBQUFBLE1BQ3ZCLHNCQUFzQjtBQUFBLE1BQ3RCLHdCQUF3QjtBQUFBLE1BQ3hCLDJCQUEyQjtBQUFBLE1BQzNCLG1CQUFtQjtBQUFBLE1BQ25CLHFCQUFxQjtBQUFBLE1BQ3JCLHNCQUFzQjtBQUFBLE1BQ3RCLHNCQUFzQjtBQUFBLE1BQ3RCLDhCQUE4QjtBQUFBLE1BQzlCLGlCQUFpQjtBQUFBLE1BQ2pCLHlCQUF5QjtBQUFBLE1BQ3pCLDJCQUEyQjtBQUFBLE1BQzNCLCtCQUErQjtBQUFBLE1BQy9CLDBCQUEwQjtBQUFBLE1BQzFCLDhCQUE4QjtBQUFBLE1BQzlCLGlCQUFpQjtBQUFBLE1BQ2pCLHVCQUF1QjtBQUFBLE1BQ3ZCLGdCQUFnQjtBQUFBLE1BQ2hCLDBCQUEwQjtBQUFBLE1BQzFCLHlCQUF5QjtBQUFBLE1BQ3pCLHNCQUFzQjtBQUFBLE1BQ3RCLGtCQUFrQjtBQUFBLE1BQ2xCLG1CQUFtQjtBQUFBLE1BQ25CLGtCQUFrQjtBQUFBLE1BQ2xCLHVCQUF1QjtBQUFBLE1BQ3ZCLG9DQUFvQztBQUFBLE1BQ3BDLHNDQUFzQztBQUFBLE1BQ3RDLHdCQUF3QjtBQUFBLE1BQ3hCLHVCQUF1QjtBQUFBLE1BQ3ZCLHlCQUF5QjtBQUFBLE1BQ3pCLDRCQUE0QjtBQUFBLE1BQzVCLDRCQUE0QjtBQUFBLE1BQzVCLGNBQWM7QUFBQSxNQUNkLGFBQWE7QUFBQSxNQUNiLGNBQWM7QUFBQSxNQUNkLG9CQUFvQjtBQUFBLE1BQ3BCLG1CQUFtQjtBQUFBLE1BQ25CLHVCQUF1QjtBQUFBLE1BQ3ZCLHNCQUFzQjtBQUFBLE1BQ3RCLHFCQUFxQjtBQUFBLE1BQ3JCLG9CQUFvQjtBQUFBLE1BQ3BCLGlCQUFpQjtBQUFBLE1BQ2pCLGdCQUFnQjtBQUFBLE1BQ2hCLG9CQUFvQjtBQUFBLE1BQ3BCLG1CQUFtQjtBQUFBLE1BQ25CLHVCQUF1QjtBQUFBLE1BQ3ZCLHNCQUFzQjtBQUFBLE1BQ3RCLHFCQUFxQjtBQUFBLE1BQ3JCLG9CQUFvQjtBQUFBLE1BQ3BCLGdCQUFnQjtBQUFBLE1BQ2hCLGVBQWU7QUFBQSxNQUNmLGVBQWU7QUFBQSxNQUNmLGNBQWM7QUFBQSxNQUNkLDBCQUEwQjtBQUFBLE1BQzFCLHlCQUF5QjtBQUFBLE1BQ3pCLHNDQUFzQztBQUFBLE1BQ3RDLHlEQUF5RDtBQUFBLE1BQ3pELDRCQUE0QjtBQUFBLE1BQzVCLDRCQUE0QjtBQUFBLE1BQzVCLDJCQUEyQjtBQUFBLE1BQzNCLDZCQUE2QjtBQUFBLE1BQzdCLDBCQUEwQjtBQUFBLElBQzNCO0FBQUEsSUFDQSxPQUFPO0FBQUEsTUFDTixvQkFBb0I7QUFBQSxNQUNwQixtQkFBbUI7QUFBQSxNQUNuQixtQkFBbUI7QUFBQSxNQUNuQixlQUFlO0FBQUEsTUFDZixnQkFBZ0I7QUFBQSxNQUNoQixvQkFBb0I7QUFBQSxJQUNyQjtBQUFBLElBQ0EsUUFBUTtBQUFBLE1BQ1Asb0JBQW9CO0FBQUEsTUFDcEIsZ0JBQWdCO0FBQUEsTUFDaEIsa0JBQWtCO0FBQUEsTUFDbEIsa0JBQWtCO0FBQUEsTUFDbEIsb0JBQW9CO0FBQUEsTUFDcEIsZUFBZTtBQUFBLE1BQ2YsZ0JBQWdCO0FBQUEsTUFDaEIsa0JBQWtCO0FBQUEsTUFDbEIsZUFBZTtBQUFBLE1BQ2YsWUFBWTtBQUFBLE1BQ1osY0FBYztBQUFBLE1BQ2QsZUFBZTtBQUFBLE1BQ2YsaUJBQWlCO0FBQUEsTUFDakIsYUFBYTtBQUFBLE1BQ2IsaUJBQWlCO0FBQUEsTUFDakIsWUFBWTtBQUFBLE1BQ1osWUFBWTtBQUFBLE1BQ1osa0JBQWtCO0FBQUEsTUFDbEIsb0JBQW9CO0FBQUEsTUFDcEIsb0JBQW9CO0FBQUEsTUFDcEIsY0FBYztBQUFBLElBQ2Y7QUFBQSxFQUNEOzs7QUR4S08sTUFBTSxRQUFRO0FBR3JCLFNBQU8sU0FBUyxPQUFPLFVBQVUsQ0FBQztBQUNsQyxTQUFPLE9BQU8scUJBQXFCO0FBRW5DLE1BQU1HLFFBQU8sdUJBQXVCLFlBQVksUUFBUSxFQUFFO0FBQzFELE1BQU0sYUFBYTtBQUNuQixNQUFNLGlCQUFpQixvQkFBSSxJQUFJO0FBRS9CLE1BQU0sV0FBTixNQUFlO0FBQUEsSUFDWCxZQUFZLFdBQVcsVUFBVSxjQUFjO0FBQzNDLFdBQUssWUFBWTtBQUNqQixXQUFLLGVBQWUsZ0JBQWdCO0FBQ3BDLFdBQUssV0FBVyxDQUFDLFNBQVM7QUFDdEIsaUJBQVMsSUFBSTtBQUNiLFlBQUksS0FBSyxpQkFBaUI7QUFBSSxpQkFBTztBQUNyQyxhQUFLLGdCQUFnQjtBQUNyQixlQUFPLEtBQUssaUJBQWlCO0FBQUEsTUFDakM7QUFBQSxJQUNKO0FBQUEsRUFDSjtBQUVPLE1BQU0sYUFBTixNQUFpQjtBQUFBLElBQ3BCLFlBQVksTUFBTSxPQUFPLE1BQU07QUFDM0IsV0FBSyxPQUFPO0FBQ1osV0FBSyxPQUFPO0FBQUEsSUFDaEI7QUFBQSxFQUNKO0FBRU8sV0FBUyxRQUFRO0FBQUEsRUFDeEI7QUFFQSxXQUFTLG1CQUFtQixPQUFPO0FBQy9CLFFBQUksWUFBWSxlQUFlLElBQUksTUFBTSxJQUFJO0FBQzdDLFFBQUksV0FBVztBQUNYLFVBQUksV0FBVyxVQUFVLE9BQU8sY0FBWTtBQUN4QyxZQUFJLFNBQVMsU0FBUyxTQUFTLEtBQUs7QUFDcEMsWUFBSTtBQUFRLGlCQUFPO0FBQUEsTUFDdkIsQ0FBQztBQUNELFVBQUksU0FBUyxTQUFTLEdBQUc7QUFDckIsb0JBQVksVUFBVSxPQUFPLE9BQUssQ0FBQyxTQUFTLFNBQVMsQ0FBQyxDQUFDO0FBQ3ZELFlBQUksVUFBVSxXQUFXO0FBQUcseUJBQWUsT0FBTyxNQUFNLElBQUk7QUFBQTtBQUN2RCx5QkFBZSxJQUFJLE1BQU0sTUFBTSxTQUFTO0FBQUEsTUFDakQ7QUFBQSxJQUNKO0FBQUEsRUFDSjtBQVdPLFdBQVMsV0FBVyxXQUFXLFVBQVUsY0FBYztBQUMxRCxRQUFJLFlBQVksZUFBZSxJQUFJLFNBQVMsS0FBSyxDQUFDO0FBQ2xELFVBQU0sZUFBZSxJQUFJLFNBQVMsV0FBVyxVQUFVLFlBQVk7QUFDbkUsY0FBVSxLQUFLLFlBQVk7QUFDM0IsbUJBQWUsSUFBSSxXQUFXLFNBQVM7QUFDdkMsV0FBTyxNQUFNLFlBQVksWUFBWTtBQUFBLEVBQ3pDO0FBUU8sV0FBUyxHQUFHLFdBQVcsVUFBVTtBQUFFLFdBQU8sV0FBVyxXQUFXLFVBQVUsRUFBRTtBQUFBLEVBQUc7QUFTL0UsV0FBUyxLQUFLLFdBQVcsVUFBVTtBQUFFLFdBQU8sV0FBVyxXQUFXLFVBQVUsQ0FBQztBQUFBLEVBQUc7QUFRdkYsV0FBUyxZQUFZLFVBQVU7QUFDM0IsVUFBTSxZQUFZLFNBQVM7QUFDM0IsUUFBSSxZQUFZLGVBQWUsSUFBSSxTQUFTLEVBQUUsT0FBTyxPQUFLLE1BQU0sUUFBUTtBQUN4RSxRQUFJLFVBQVUsV0FBVztBQUFHLHFCQUFlLE9BQU8sU0FBUztBQUFBO0FBQ3RELHFCQUFlLElBQUksV0FBVyxTQUFTO0FBQUEsRUFDaEQ7QUFVTyxXQUFTLElBQUksY0FBYyxzQkFBc0I7QUFDcEQsUUFBSSxpQkFBaUIsQ0FBQyxXQUFXLEdBQUcsb0JBQW9CO0FBQ3hELG1CQUFlLFFBQVEsQ0FBQUMsZUFBYSxlQUFlLE9BQU9BLFVBQVMsQ0FBQztBQUFBLEVBQ3hFO0FBT08sV0FBUyxTQUFTO0FBQUUsbUJBQWUsTUFBTTtBQUFBLEVBQUc7QUFRNUMsV0FBUyxLQUFLLE9BQU87QUFBRSxXQUFPRCxNQUFLLFlBQVksS0FBSztBQUFBLEVBQUc7OztBRTNJOUQ7QUFBQTtBQUFBLGlCQUFBRTtBQUFBLElBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBNEVBLFNBQU8sU0FBUyxPQUFPLFVBQVUsQ0FBQztBQUNsQyxTQUFPLE9BQU8sc0JBQXNCO0FBQ3BDLFNBQU8sT0FBTyx1QkFBdUI7QUFPckMsTUFBTSxhQUFhO0FBQ25CLE1BQU0sZ0JBQWdCO0FBQ3RCLE1BQU0sY0FBYztBQUNwQixNQUFNLGlCQUFpQjtBQUN2QixNQUFNLGlCQUFpQjtBQUN2QixNQUFNLGlCQUFpQjtBQUV2QixNQUFNQyxRQUFPLHVCQUF1QixZQUFZLFFBQVEsRUFBRTtBQUMxRCxNQUFNLGtCQUFrQixvQkFBSSxJQUFJO0FBTWhDLFdBQVMsYUFBYTtBQUNsQixRQUFJO0FBQ0osT0FBRztBQUNDLGVBQVMsT0FBTztBQUFBLElBQ3BCLFNBQVMsZ0JBQWdCLElBQUksTUFBTTtBQUNuQyxXQUFPO0FBQUEsRUFDWDtBQVFBLFdBQVMsT0FBTyxNQUFNLFVBQVUsQ0FBQyxHQUFHO0FBQ2hDLFVBQU0sS0FBSyxXQUFXO0FBQ3RCLFlBQVEsV0FBVyxJQUFJO0FBQ3ZCLFdBQU8sSUFBSSxRQUFRLENBQUMsU0FBUyxXQUFXO0FBQ3BDLHNCQUFnQixJQUFJLElBQUksRUFBQyxTQUFTLE9BQU0sQ0FBQztBQUN6QyxNQUFBQSxNQUFLLE1BQU0sT0FBTyxFQUFFLE1BQU0sQ0FBQyxVQUFVO0FBQ2pDLGVBQU8sS0FBSztBQUNaLHdCQUFnQixPQUFPLEVBQUU7QUFBQSxNQUM3QixDQUFDO0FBQUEsSUFDTCxDQUFDO0FBQUEsRUFDTDtBQVdBLFdBQVMscUJBQXFCLElBQUksTUFBTSxRQUFRO0FBQzVDLFFBQUksSUFBSSxnQkFBZ0IsSUFBSSxFQUFFO0FBQzlCLFFBQUksR0FBRztBQUNILFVBQUksUUFBUTtBQUNSLFVBQUUsUUFBUSxLQUFLLE1BQU0sSUFBSSxDQUFDO0FBQUEsTUFDOUIsT0FBTztBQUNILFVBQUUsUUFBUSxJQUFJO0FBQUEsTUFDbEI7QUFDQSxzQkFBZ0IsT0FBTyxFQUFFO0FBQUEsSUFDN0I7QUFBQSxFQUNKO0FBVUEsV0FBUyxvQkFBb0IsSUFBSSxTQUFTO0FBQ3RDLFFBQUksSUFBSSxnQkFBZ0IsSUFBSSxFQUFFO0FBQzlCLFFBQUksR0FBRztBQUNILFFBQUUsT0FBTyxPQUFPO0FBQ2hCLHNCQUFnQixPQUFPLEVBQUU7QUFBQSxJQUM3QjtBQUFBLEVBQ0o7QUFTTyxNQUFNLE9BQU8sQ0FBQyxZQUFZLE9BQU8sWUFBWSxPQUFPO0FBTXBELE1BQU0sVUFBVSxDQUFDLFlBQVksT0FBTyxlQUFlLE9BQU87QUFNMUQsTUFBTUMsU0FBUSxDQUFDLFlBQVksT0FBTyxhQUFhLE9BQU87QUFNdEQsTUFBTSxXQUFXLENBQUMsWUFBWSxPQUFPLGdCQUFnQixPQUFPO0FBTTVELE1BQU0sV0FBVyxDQUFDLFlBQVksT0FBTyxnQkFBZ0IsT0FBTztBQU01RCxNQUFNLFdBQVcsQ0FBQyxZQUFZLE9BQU8sZ0JBQWdCLE9BQU87OztBSHpMbkUsV0FBUyxVQUFVLFdBQVcsT0FBSyxNQUFNO0FBQ3JDLFFBQUksUUFBUSxJQUFJLFdBQVcsV0FBVyxJQUFJO0FBQzFDLFNBQUssS0FBSztBQUFBLEVBQ2Q7QUFPQSxXQUFTLHVCQUF1QjtBQUM1QixVQUFNLFdBQVcsU0FBUyxpQkFBaUIsYUFBYTtBQUN4RCxhQUFTLFFBQVEsU0FBVSxTQUFTO0FBQ2hDLFlBQU0sWUFBWSxRQUFRLGFBQWEsV0FBVztBQUNsRCxZQUFNLFVBQVUsUUFBUSxhQUFhLGFBQWE7QUFDbEQsWUFBTSxVQUFVLFFBQVEsYUFBYSxhQUFhLEtBQUs7QUFFdkQsVUFBSSxXQUFXLFdBQVk7QUFDdkIsWUFBSSxTQUFTO0FBQ1QsbUJBQVMsRUFBQyxPQUFPLFdBQVcsU0FBUSxTQUFTLFVBQVUsT0FBTyxTQUFRLENBQUMsRUFBQyxPQUFNLE1BQUssR0FBRSxFQUFDLE9BQU0sTUFBTSxXQUFVLEtBQUksQ0FBQyxFQUFDLENBQUMsRUFBRSxLQUFLLFNBQVUsUUFBUTtBQUN4SSxnQkFBSSxXQUFXLE1BQU07QUFDakIsd0JBQVUsU0FBUztBQUFBLFlBQ3ZCO0FBQUEsVUFDSixDQUFDO0FBQ0Q7QUFBQSxRQUNKO0FBQ0Esa0JBQVUsU0FBUztBQUFBLE1BQ3ZCO0FBR0EsY0FBUSxvQkFBb0IsU0FBUyxRQUFRO0FBRzdDLGNBQVEsaUJBQWlCLFNBQVMsUUFBUTtBQUFBLElBQzlDLENBQUM7QUFBQSxFQUNMO0FBUUEsV0FBUyxpQkFBaUIsWUFBWSxRQUFRO0FBQzFDLFFBQUksZUFBZSxJQUFJLFVBQVU7QUFDakMsUUFBSSxZQUFZLGNBQWMsWUFBWTtBQUMxQyxRQUFJLENBQUMsVUFBVSxJQUFJLE1BQU0sR0FBRztBQUN4QixjQUFRLElBQUksbUJBQW1CLFNBQVMsWUFBWTtBQUFBLElBQ3hEO0FBQ0EsUUFBSTtBQUNBLGdCQUFVLElBQUksTUFBTSxFQUFFO0FBQUEsSUFDMUIsU0FBUyxHQUFHO0FBQ1IsY0FBUSxNQUFNLGtDQUFrQyxTQUFTLFFBQVEsQ0FBQztBQUFBLElBQ3RFO0FBQUEsRUFDSjtBQVFBLFdBQVMsd0JBQXdCO0FBQzdCLFVBQU0sV0FBVyxTQUFTLGlCQUFpQixjQUFjO0FBQ3pELGFBQVMsUUFBUSxTQUFVLFNBQVM7QUFDaEMsWUFBTSxlQUFlLFFBQVEsYUFBYSxZQUFZO0FBQ3RELFlBQU0sVUFBVSxRQUFRLGFBQWEsYUFBYTtBQUNsRCxZQUFNLFVBQVUsUUFBUSxhQUFhLGFBQWEsS0FBSztBQUN2RCxZQUFNLGVBQWUsUUFBUSxhQUFhLG1CQUFtQixLQUFLO0FBRWxFLFVBQUksV0FBVyxXQUFZO0FBQ3ZCLFlBQUksU0FBUztBQUNULG1CQUFTLEVBQUMsT0FBTyxXQUFXLFNBQVEsU0FBUyxTQUFRLENBQUMsRUFBQyxPQUFNLE1BQUssR0FBRSxFQUFDLE9BQU0sTUFBTSxXQUFVLEtBQUksQ0FBQyxFQUFDLENBQUMsRUFBRSxLQUFLLFNBQVUsUUFBUTtBQUN2SCxnQkFBSSxXQUFXLE1BQU07QUFDakIsK0JBQWlCLGNBQWMsWUFBWTtBQUFBLFlBQy9DO0FBQUEsVUFDSixDQUFDO0FBQ0Q7QUFBQSxRQUNKO0FBQ0EseUJBQWlCLGNBQWMsWUFBWTtBQUFBLE1BQy9DO0FBR0EsY0FBUSxvQkFBb0IsU0FBUyxRQUFRO0FBRzdDLGNBQVEsaUJBQWlCLFNBQVMsUUFBUTtBQUFBLElBQzlDLENBQUM7QUFBQSxFQUNMO0FBV0EsV0FBUyw0QkFBNEI7QUFDakMsVUFBTSxXQUFXLFNBQVMsaUJBQWlCLGVBQWU7QUFDMUQsYUFBUyxRQUFRLFNBQVUsU0FBUztBQUNoQyxZQUFNLE1BQU0sUUFBUSxhQUFhLGFBQWE7QUFDOUMsWUFBTSxVQUFVLFFBQVEsYUFBYSxhQUFhO0FBQ2xELFlBQU0sVUFBVSxRQUFRLGFBQWEsYUFBYSxLQUFLO0FBRXZELFVBQUksV0FBVyxXQUFZO0FBQ3ZCLFlBQUksU0FBUztBQUNULG1CQUFTLEVBQUMsT0FBTyxXQUFXLFNBQVEsU0FBUyxTQUFRLENBQUMsRUFBQyxPQUFNLE1BQUssR0FBRSxFQUFDLE9BQU0sTUFBTSxXQUFVLEtBQUksQ0FBQyxFQUFDLENBQUMsRUFBRSxLQUFLLFNBQVUsUUFBUTtBQUN2SCxnQkFBSSxXQUFXLE1BQU07QUFDakIsbUJBQUssUUFBUSxHQUFHO0FBQUEsWUFDcEI7QUFBQSxVQUNKLENBQUM7QUFDRDtBQUFBLFFBQ0o7QUFDQSxhQUFLLFFBQVEsR0FBRztBQUFBLE1BQ3BCO0FBR0EsY0FBUSxvQkFBb0IsU0FBUyxRQUFRO0FBRzdDLGNBQVEsaUJBQWlCLFNBQVMsUUFBUTtBQUFBLElBQzlDLENBQUM7QUFBQSxFQUNMO0FBT08sV0FBUyxTQUFTO0FBQ3JCLHlCQUFxQjtBQUNyQiwwQkFBc0I7QUFDdEIsOEJBQTBCO0FBQUEsRUFDOUI7QUFNQSxXQUFTLGNBQWMsY0FBYztBQUVqQyxRQUFJLFNBQVMsb0JBQUksSUFBSTtBQUdyQixhQUFTLFVBQVUsY0FBYztBQUU3QixVQUFHLE9BQU8sYUFBYSxNQUFNLE1BQU0sWUFBWTtBQUUzQyxlQUFPLElBQUksUUFBUSxhQUFhLE1BQU0sQ0FBQztBQUFBLE1BQzNDO0FBQUEsSUFFSjtBQUVBLFdBQU87QUFBQSxFQUNYOzs7QUkxS0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFlQSxTQUFPLFNBQVMsT0FBTyxVQUFVLENBQUM7QUFDbEMsU0FBTyxPQUFPLG9CQUFvQjtBQUNsQyxTQUFPLE9BQU8sbUJBQW1CO0FBR2pDLE1BQU0sY0FBYztBQUNwQixNQUFNQyxRQUFPLHVCQUF1QixZQUFZLE1BQU0sRUFBRTtBQUN4RCxNQUFJLGdCQUFnQixvQkFBSSxJQUFJO0FBTzVCLFdBQVNDLGNBQWE7QUFDbEIsUUFBSTtBQUNKLE9BQUc7QUFDQyxlQUFTLE9BQU87QUFBQSxJQUNwQixTQUFTLGNBQWMsSUFBSSxNQUFNO0FBQ2pDLFdBQU87QUFBQSxFQUNYO0FBV0EsV0FBUyxjQUFjLElBQUksTUFBTSxRQUFRO0FBQ3JDLFVBQU0saUJBQWlCLHFCQUFxQixFQUFFO0FBQzlDLFFBQUksZ0JBQWdCO0FBQ2hCLHFCQUFlLFFBQVEsU0FBUyxLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUk7QUFBQSxJQUMzRDtBQUFBLEVBQ0o7QUFVQSxXQUFTLGFBQWEsSUFBSSxTQUFTO0FBQy9CLFVBQU0saUJBQWlCLHFCQUFxQixFQUFFO0FBQzlDLFFBQUksZ0JBQWdCO0FBQ2hCLHFCQUFlLE9BQU8sT0FBTztBQUFBLElBQ2pDO0FBQUEsRUFDSjtBQVNBLFdBQVMscUJBQXFCLElBQUk7QUFDOUIsVUFBTSxXQUFXLGNBQWMsSUFBSSxFQUFFO0FBQ3JDLGtCQUFjLE9BQU8sRUFBRTtBQUN2QixXQUFPO0FBQUEsRUFDWDtBQVNBLFdBQVMsWUFBWSxNQUFNLFVBQVUsQ0FBQyxHQUFHO0FBQ3JDLFdBQU8sSUFBSSxRQUFRLENBQUMsU0FBUyxXQUFXO0FBQ3BDLFlBQU0sS0FBS0EsWUFBVztBQUN0QixjQUFRLFNBQVMsSUFBSTtBQUNyQixvQkFBYyxJQUFJLElBQUksRUFBRSxTQUFTLE9BQU8sQ0FBQztBQUN6QyxNQUFBRCxNQUFLLE1BQU0sT0FBTyxFQUFFLE1BQU0sQ0FBQyxVQUFVO0FBQ2pDLGVBQU8sS0FBSztBQUNaLHNCQUFjLE9BQU8sRUFBRTtBQUFBLE1BQzNCLENBQUM7QUFBQSxJQUNMLENBQUM7QUFBQSxFQUNMO0FBUU8sV0FBUyxLQUFLLFNBQVM7QUFDMUIsV0FBTyxZQUFZLGFBQWEsT0FBTztBQUFBLEVBQzNDO0FBVU8sV0FBUyxPQUFPLFNBQVMsTUFBTTtBQUNsQyxRQUFJLE9BQU8sU0FBUyxZQUFZLEtBQUssTUFBTSxHQUFHLEVBQUUsV0FBVyxHQUFHO0FBQzFELFlBQU0sSUFBSSxNQUFNLG9FQUFvRTtBQUFBLElBQ3hGO0FBQ0EsUUFBSSxDQUFDLGFBQWEsWUFBWSxVQUFVLElBQUksS0FBSyxNQUFNLEdBQUc7QUFDMUQsV0FBTyxZQUFZLGFBQWE7QUFBQSxNQUM1QjtBQUFBLE1BQ0E7QUFBQSxNQUNBO0FBQUEsTUFDQTtBQUFBLElBQ0osQ0FBQztBQUFBLEVBQ0w7QUFTTyxXQUFTLEtBQUssYUFBYSxNQUFNO0FBQ3BDLFdBQU8sWUFBWSxhQUFhO0FBQUEsTUFDNUI7QUFBQSxNQUNBO0FBQUEsSUFDSixDQUFDO0FBQUEsRUFDTDtBQVVPLFdBQVMsT0FBTyxZQUFZLGVBQWUsTUFBTTtBQUNwRCxXQUFPLFlBQVksYUFBYTtBQUFBLE1BQzVCLGFBQWE7QUFBQSxNQUNiLFlBQVk7QUFBQSxNQUNaO0FBQUEsTUFDQTtBQUFBLElBQ0osQ0FBQztBQUFBLEVBQ0w7OztBQ3BKQSxTQUFPLFNBQVMsT0FBTyxVQUFVLENBQUM7QUFnRGxDLFNBQU8sT0FBTyxTQUFPO0FBRXJCLFNBQU8sUUFBUSxPQUFPLFNBQVMsQ0FBQztBQUNoQyxTQUFPLE1BQU0sY0FBYztBQUMzQixTQUFPLE1BQU0sVUFBVTtBQUN2QixTQUFPLE1BQU0sT0FBTztBQUNwQixTQUFPLE1BQU0sWUFBWTtBQUN6QixTQUFPLE1BQU0sVUFBVTtBQUN2QixTQUFPLE1BQU0sU0FBUztBQUN0QixTQUFPLE1BQU0sUUFBUTtBQUNyQixTQUFPLE1BQU0sVUFBVTtBQUN2QixTQUFPLE1BQU0sU0FBUztBQUN0QixTQUFPLE1BQU0sU0FBUztBQUN0QixTQUFPLE1BQU0sTUFBTTtBQUduQixNQUFJLFVBQVU7QUFDZCxXQUFTLGlCQUFpQixvQkFBb0IsV0FBVztBQUNyRCxjQUFVO0FBQ1YsV0FBTyxPQUFPLE9BQU8scUJBQXFCO0FBQzFDLFFBQUcsTUFBTztBQUNOLGVBQVMsc0JBQXNCO0FBQUEsSUFDbkM7QUFBQSxFQUNKLENBQUM7QUFFRCxXQUFTLFVBQVUsSUFBSTtBQUNuQixRQUFJLFdBQVcsU0FBUyxlQUFlLFlBQVk7QUFDL0MsU0FBRztBQUFBLElBQ1AsT0FBTztBQUNILGVBQVMsaUJBQWlCLG9CQUFvQixFQUFFO0FBQUEsSUFDcEQ7QUFBQSxFQUNKO0FBRUEsWUFBVSxNQUFNO0FBQ1osSUFBSSxPQUFPO0FBQUEsRUFDZixDQUFDOyIsCiAgIm5hbWVzIjogWyJzaXplIiwgImNhbGwiLCAiY2FsbCIsICJjYWxsIiwgImNhbGwiLCAiY2FsbCIsICJIaWRlIiwgIlNob3ciLCAic2V0UmVzaXphYmxlIiwgImNhbGwiLCAid2lkdGgiLCAiaGVpZ2h0IiwgInJlc2l6YWJsZSIsICJIaWRlIiwgIlNob3ciLCAiY2FsbCIsICJldmVudE5hbWUiLCAiRXJyb3IiLCAiY2FsbCIsICJFcnJvciIsICJjYWxsIiwgImdlbmVyYXRlSUQiXQp9Cg== diff --git a/v3/internal/commands/build_assets/runtime/runtime.js b/v3/internal/commands/build_assets/runtime/runtime.js deleted file mode 100644 index baaccee0402..00000000000 --- a/v3/internal/commands/build_assets/runtime/runtime.js +++ /dev/null @@ -1 +0,0 @@ -(()=>{var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return q(Ce,{text:e})}function Me(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); diff --git a/v3/internal/commands/runtime.go b/v3/internal/commands/runtime.go deleted file mode 100644 index d62bf5ed429..00000000000 --- a/v3/internal/commands/runtime.go +++ /dev/null @@ -1,21 +0,0 @@ -package commands - -import ( - "github.com/wailsapp/wails/v3/internal/commands/build_assets/runtime" - "os" -) - -type GenerateRuntimeOptions struct { -} - -func GenerateRuntime(options *GenerateRuntimeOptions) error { - err := os.WriteFile("runtime.js", runtime.RuntimeJS, 0644) - if err != nil { - return err - } - err = os.WriteFile("runtime.debug.js", runtime.RuntimeDebugJS, 0644) - if err != nil { - return err - } - return nil -} diff --git a/v3/internal/runtime/Taskfile.yaml b/v3/internal/runtime/Taskfile.yaml index 794769b2856..20ae28fd28c 100644 --- a/v3/internal/runtime/Taskfile.yaml +++ b/v3/internal/runtime/Taskfile.yaml @@ -21,12 +21,12 @@ tasks: build:debug: internal: true cmds: - - npx esbuild@latest desktop/compiled/main.js --bundle --tree-shaking=true --sourcemap=inline --outfile=../commands/build_assets/runtime/runtime.debug.js --define:DEBUG=true + - npx esbuild@latest desktop/compiled/main.js --bundle --tree-shaking=true --sourcemap=inline --outfile=../assetserver/assets/runtime.debug.js --define:DEBUG=true build:production: internal: true cmds: - - npx esbuild@latest desktop/compiled/main.js --bundle --tree-shaking=true --minify --outfile=../commands/build_assets/runtime/runtime.js --define:DEBUG=false --drop:console + - npx esbuild@latest desktop/compiled/main.js --bundle --tree-shaking=true --minify --outfile=../assetserver/assets/runtime.js --define:DEBUG=false --drop:console build:all: internal: true @@ -35,14 +35,6 @@ tasks: - build:production cmds: - - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/binding/assets/runtime.js - - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/frameless/assets/runtime.js - - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/window-api/assets/runtime.js - - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/contextmenus/assets/runtime.js - - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/wml/assets/runtime.js - - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../internal/commands/build_assets/runtime/runtime.js - - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../examples/screen/assets/runtime.js - - cmd: wails3 tool cp ../commands/build_assets/runtime/runtime.js ../../pkg/application/assets/alpha/runtime.js - cmd: echo "Build Complete." build: diff --git a/v3/pkg/application/application.go b/v3/pkg/application/application.go index 03b9d19d7bf..6c8814d719d 100644 --- a/v3/pkg/application/application.go +++ b/v3/pkg/application/application.go @@ -30,7 +30,7 @@ var globalApplication *App // AlphaAssets is the default assets for the alpha application var AlphaAssets = AssetOptions{ - Handler: AssetFileServerFS(alphaAssets), + Handler: BundledAssetFileServer(alphaAssets), } func init() { diff --git a/v3/pkg/application/application_options.go b/v3/pkg/application/application_options.go index e786c66a541..c190d29d02c 100644 --- a/v3/pkg/application/application_options.go +++ b/v3/pkg/application/application_options.go @@ -115,6 +115,15 @@ func AssetFileServerFS(assets fs.FS) http.Handler { return assetserver.NewAssetFileServer(assets) } +// BundledAssetFileServer returns a http handler which serves the assets from the fs.FS. +// If an external devserver has been provided 'FRONTEND_DEVSERVER_URL' the files are being served +// from the external server, ignoring the `assets`. +// It also serves the compiled runtime.js file at `/wails/runtime.js`. +// It will provide the production runtime.js file from the embedded assets if the `production` tag is used. +func BundledAssetFileServer(assets fs.FS) http.Handler { + return assetserver.NewBundledAssetFileServer(assets) +} + /******** Mac Options ********/ // ActivationPolicy is the activation policy for the application. diff --git a/v3/pkg/application/assets/alpha/index.html b/v3/pkg/application/assets/alpha/index.html index ca7980bb63a..a0140e2d18e 100644 --- a/v3/pkg/application/assets/alpha/index.html +++ b/v3/pkg/application/assets/alpha/index.html @@ -67,7 +67,7 @@ } - + {var de=Object.defineProperty;var w=(e,i)=>{for(var n in i)de(e,n,{get:i[n],enumerable:!0})};var T={};w(T,{Hide:()=>We,Quit:()=>fe,Show:()=>ge});var le="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";var f=(e=21)=>{let i="",n=e;for(;n--;)i+=le[Math.random()*64|0];return i};var ce=window.location.origin+"/wails/runtime",d={Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9},se=f();function l(e,i){return function(n,o=null){return we(e,n,i,o)}}function we(e,i,n,o){let t=new URL(ce);t.searchParams.append("object",e),t.searchParams.append("method",i);let a={headers:{}};return n&&(a.headers["x-wails-window-name"]=n),o&&t.searchParams.append("args",JSON.stringify(o)),a.headers["x-wails-client-id"]=se,new Promise((s,p)=>{fetch(t,a).then(c=>{if(c.ok)return c.headers.get("Content-Type")&&c.headers.get("Content-Type").indexOf("application/json")!==-1?c.json():c.text();p(Error(c.statusText))}).then(c=>s(c)).catch(c=>p(c))})}var P=l(d.Application,""),me=0,ue=1,pe=2;function We(){return P(me)}function ge(){return P(ue)}function fe(){return P(pe)}var B={};w(B,{OpenURL:()=>b});var he=l(d.Browser,""),De=0;function b(e){return he(De,{url:e})}var I={};w(I,{SetText:()=>xe,Text:()=>Me});var q=l(d.Clipboard,""),Ce=0,Se=1;function xe(e){return q(Ce,{text:e})}function Me(){return q(Se)}var L={};w(L,{Capabilities:()=>Re,Environment:()=>Ee,IsAMD64:()=>Oe,IsARM:()=>Pe,IsARM64:()=>Te,IsDarkMode:()=>be,IsDebug:()=>F,IsLinux:()=>Ue,IsMac:()=>ye,IsWindows:()=>R,invoke:()=>h});var J=l(d.System,""),Ae=0,ve=1;function h(e){return window.chrome?window.chrome.webview.postMessage(e):window.webkit.messageHandlers.external.postMessage(e)}function be(){return J(Ae)}function Re(){return fetch("/wails/capabilities").json()}function Ee(){return J(ve)}function R(){return window._wails.environment.OS==="windows"}function Ue(){return window._wails.environment.OS==="linux"}function ye(){return window._wails.environment.OS==="darwin"}function Oe(){return window._wails.environment.Arch==="amd64"}function Pe(){return window._wails.environment.Arch==="arm"}function Te(){return window._wails.environment.Arch==="arm64"}function F(){return window._wails.environment.Debug===!0}window.addEventListener("contextmenu",Le);var Be=l(d.ContextMenu,""),Ie=0;function Fe(e,i,n,o){Be(Ie,{id:e,x:i,y:n,data:o})}function Le(e){let i=e.target,n=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu");if(n=n?n.trim():"",n){e.preventDefault();let o=window.getComputedStyle(i).getPropertyValue("--custom-contextmenu-data");Fe(n,e.clientX,e.clientY,o);return}ze(e)}function ze(e){if(F())return;let i=e.target;switch(window.getComputedStyle(i).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(i.isContentEditable)return;let t=window.getSelection(),a=t.toString().length>0;if(a)for(let s=0;sS});function S(e){try{return window._wails.flags[e]}catch(i){throw new Error("Unable to retrieve flag '"+e+"': "+i)}}window._wails=window._wails||{};window._wails.setResizable=He;window._wails.endDrag=ee;window.addEventListener("mousedown",_e);window.addEventListener("mousemove",Ge);window.addEventListener("mouseup",je);var x=!1,E=null,$=!1,ke="auto";function Ne(e){let i=window.getComputedStyle(e.target).getPropertyValue("--webkit-app-region");return!i||i===""||i.trim()!=="drag"||e.buttons!==1?!1:e.detail===1}function He(e){$=e}function ee(){document.body.style.cursor="default",x=!1}function Ve(){return E?(h(`resize:${E}`),!0):!1}function _e(e){(R()&&Ve()||Ne(e))&&(x=!!Ze(e))}function Ze(e){return!(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight)}function je(e){(e.buttons!==void 0?e.buttons:e.which)>0&&ee()}function u(e=ke){document.documentElement.style.cursor=e,E=e}function Ge(e){x=Ye(e),R()&&$&&Ke(e)}function Ye(e){let i=e.buttons!==void 0?e.buttons:e.which;return x&&i>0?(h("drag"),!1):x}function Ke(e){let i=S("system.resizeHandleHeight")||5,n=S("system.resizeHandleWidth")||5,o=S("resizeCornerExtra")||10,t=window.outerWidth-e.clientXJe,GetCurrent:()=>ei,GetPrimary:()=>$e});var k=l(d.Screens,""),Xe=0,Qe=1,qe=2;function Je(){return k(Xe)}function $e(){return k(Qe)}function ei(){return k(qe)}var H={};w(H,{Center:()=>Oi,Close:()=>Qi,Fullscreen:()=>Ti,Get:()=>U,GetZoomLevel:()=>rn,Height:()=>en,Hide:()=>Vi,Maximise:()=>_i,Minimise:()=>Gi,RelativePosition:()=>Ni,Restore:()=>Ki,Screen:()=>Hi,SetAlwaysOnTop:()=>zi,SetBackgroundColour:()=>qi,SetMaxSize:()=>Fi,SetMinSize:()=>Li,SetRelativePosition:()=>ki,SetResizable:()=>Ji,SetSize:()=>Bi,SetTitle:()=>Pi,SetZoomLevel:()=>an,Show:()=>Xi,Size:()=>Ii,ToggleMaximise:()=>ji,UnMaximise:()=>Zi,UnMinimise:()=>Yi,Width:()=>$i,ZoomIn:()=>nn,ZoomOut:()=>on,ZoomReset:()=>tn});var ii=0,ni=1,oi=2,ti=3,ri=4,ai=5,di=6,li=7,ci=8,si=9,wi=10,mi=11,ui=12,pi=13,Wi=14,gi=15,fi=16,hi=17,Di=18,Ci=19,Si=20,xi=21,Mi=22,Ai=23,vi=24,bi=25,Ri=26,Ei=27,Ui=28,yi=29,r=U("");function ie(e){return{Get:i=>ie(l(d.Window,i)),Center:()=>e(ii),SetTitle:i=>e(ni,{title:i}),Fullscreen:()=>e(oi),UnFullscreen:()=>e(ti),SetSize:(i,n)=>e(ri,{width:i,height:n}),Size:()=>e(ai),SetMaxSize:(i,n)=>e(di,{width:i,height:n}),SetMinSize:(i,n)=>e(li,{width:i,height:n}),SetAlwaysOnTop:i=>e(ci,{alwaysOnTop:i}),SetRelativePosition:(i,n)=>e(si,{x:i,y:n}),RelativePosition:()=>e(wi),Screen:()=>e(mi),Hide:()=>e(ui),Maximise:()=>e(pi),UnMaximise:()=>e(Wi),ToggleMaximise:()=>e(gi),Minimise:()=>e(fi),UnMinimise:()=>e(hi),Restore:()=>e(Di),Show:()=>e(Ci),Close:()=>e(Si),SetBackgroundColour:(i,n,o,t)=>e(xi,{r:i,g:n,b:o,a:t}),SetResizable:i=>e(Mi,{resizable:i}),Width:()=>e(Ai),Height:()=>e(vi),ZoomIn:()=>e(bi),ZoomOut:()=>e(Ri),ZoomReset:()=>e(Ei),GetZoomLevel:()=>e(Ui),SetZoomLevel:i=>e(yi,{zoomLevel:i})}}function U(e){return ie(l(d.Window,e))}function Oi(){r.Center()}function Pi(e){r.SetTitle(e)}function Ti(){r.Fullscreen()}function Bi(e,i){r.SetSize(e,i)}function Ii(){return r.Size()}function Fi(e,i){r.SetMaxSize(e,i)}function Li(e,i){r.SetMinSize(e,i)}function zi(e){r.SetAlwaysOnTop(e)}function ki(e,i){r.SetRelativePosition(e,i)}function Ni(){return r.RelativePosition()}function Hi(){return r.Screen()}function Vi(){r.Hide()}function _i(){r.Maximise()}function Zi(){r.UnMaximise()}function ji(){r.ToggleMaximise()}function Gi(){r.Minimise()}function Yi(){r.UnMinimise()}function Ki(){r.Restore()}function Xi(){r.Show()}function Qi(){r.Close()}function qi(e,i,n,o){r.SetBackgroundColour(e,i,n,o)}function Ji(e){r.SetResizable(e)}function $i(){return r.Width()}function en(){return r.Height()}function nn(){r.ZoomIn()}function on(){r.ZoomOut()}function tn(){r.ZoomReset()}function rn(){return r.GetZoomLevel()}function an(e){r.SetZoomLevel(e)}var K={};w(K,{Reload:()=>Y});var j={};w(j,{Emit:()=>Z,Off:()=>Wn,OffAll:()=>gn,On:()=>mn,OnMultiple:()=>_,Once:()=>un,Types:()=>dn,WailsEvent:()=>M,setup:()=>sn});var ne={Windows:{SystemThemeChanged:"windows:SystemThemeChanged",APMPowerStatusChange:"windows:APMPowerStatusChange",APMSuspend:"windows:APMSuspend",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMPowerSettingChange:"windows:APMPowerSettingChange",ApplicationStarted:"windows:ApplicationStarted",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowInactive:"windows:WindowInactive",WindowActive:"windows:WindowActive",WindowClickActive:"windows:WindowClickActive",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise",WindowFullscreen:"windows:WindowFullscreen",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowRestore:"windows:WindowRestore",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowClose:"windows:WindowClose",WindowSetFocus:"windows:WindowSetFocus",WindowKillFocus:"windows:WindowKillFocus",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver"},Mac:{ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActiveNotification:"mac:ApplicationDidResignActiveNotification",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme!",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen!",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidChangeVisibility:"mac:WindowDidChangeVisibility",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidUpdateVisibility:"mac:WindowDidUpdateVisibility",WindowShouldClose:"mac:WindowShouldClose!",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",MenuWillOpen:"mac:MenuWillOpen",MenuDidOpen:"mac:MenuDidOpen",MenuDidClose:"mac:MenuDidClose",MenuWillSendAction:"mac:MenuWillSendAction",MenuDidSendAction:"mac:MenuDidSendAction",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuWillAddItem:"mac:MenuWillAddItem",MenuDidAddItem:"mac:MenuDidAddItem",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuWillUpdate:"mac:MenuWillUpdate",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillPopUp:"mac:MenuWillPopUp",MenuDidPopUp:"mac:MenuDidPopUp",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowFileDraggingExited:"mac:WindowFileDraggingExited"},Linux:{SystemThemeChanged:"linux:SystemThemeChanged",WindowLoadChanged:"linux:WindowLoadChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",ApplicationStartup:"linux:ApplicationStartup"},Common:{ApplicationStarted:"common:ApplicationStarted",WindowMaximise:"common:WindowMaximise",WindowUnMaximise:"common:WindowUnMaximise",WindowFullscreen:"common:WindowFullscreen",WindowUnFullscreen:"common:WindowUnFullscreen",WindowRestore:"common:WindowRestore",WindowMinimise:"common:WindowMinimise",WindowUnMinimise:"common:WindowUnMinimise",WindowClosing:"common:WindowClosing",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset",WindowFocus:"common:WindowFocus",WindowLostFocus:"common:WindowLostFocus",WindowShow:"common:WindowShow",WindowHide:"common:WindowHide",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowRuntimeReady:"common:WindowRuntimeReady",ThemeChanged:"common:ThemeChanged"}};var dn=ne;window._wails=window._wails||{};window._wails.dispatchWailsEvent=wn;var ln=l(d.Events,""),cn=0,m=new Map,V=class{constructor(i,n,o){this.eventName=i,this.maxCallbacks=o||-1,this.Callback=t=>(n(t),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},M=class{constructor(i,n=null){this.name=i,this.data=n}};function sn(){}function wn(e){let i=m.get(e.name);if(i){let n=i.filter(o=>{if(o.Callback(e))return!0});n.length>0&&(i=i.filter(o=>!n.includes(o)),i.length===0?m.delete(e.name):m.set(e.name,i))}}function _(e,i,n){let o=m.get(e)||[],t=new V(e,i,n);return o.push(t),m.set(e,o),()=>pn(t)}function mn(e,i){return _(e,i,-1)}function un(e,i){return _(e,i,1)}function pn(e){let i=e.eventName,n=m.get(i).filter(o=>o!==e);n.length===0?m.delete(i):m.set(i,n)}function Wn(e,...i){[e,...i].forEach(o=>m.delete(o))}function gn(){m.clear()}function Z(e){return ln(cn,e)}var G={};w(G,{Error:()=>Un,Info:()=>Rn,OpenFile:()=>yn,Question:()=>A,SaveFile:()=>On,Warning:()=>En});window._wails=window._wails||{};window._wails.dialogErrorCallback=bn;window._wails.dialogResultCallback=vn;var fn=0,hn=1,Dn=2,Cn=3,Sn=4,xn=5,Mn=l(d.Dialog,""),W=new Map;function An(){let e;do e=f();while(W.has(e));return e}function D(e,i={}){let n=An();return i["dialog-id"]=n,new Promise((o,t)=>{W.set(n,{resolve:o,reject:t}),Mn(e,i).catch(a=>{t(a),W.delete(n)})})}function vn(e,i,n){let o=W.get(e);o&&(n?o.resolve(JSON.parse(i)):o.resolve(i),W.delete(e))}function bn(e,i){let n=W.get(e);n&&(n.reject(i),W.delete(e))}var Rn=e=>D(fn,e),En=e=>D(hn,e),Un=e=>D(Dn,e),A=e=>D(Cn,e),yn=e=>D(Sn,e),On=e=>D(xn,e);function oe(e,i=null){let n=new M(e,i);Z(n)}function Pn(){document.querySelectorAll("[wml-event]").forEach(function(i){let n=i.getAttribute("wml-event"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&oe(n)});return}oe(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function te(e,i){let n=U(e),o=In(n);o.has(i);try{o.get(i)()}catch{}}function Tn(){document.querySelectorAll("[wml-window]").forEach(function(i){let n=i.getAttribute("wml-window"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=i.getAttribute("wml-target-window")||"",s=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(p){p!=="No"&&te(a,n)});return}te(a,n)};i.removeEventListener(t,s),i.addEventListener(t,s)})}function Bn(){document.querySelectorAll("[wml-openurl]").forEach(function(i){let n=i.getAttribute("wml-openurl"),o=i.getAttribute("wml-confirm"),t=i.getAttribute("wml-trigger")||"click",a=function(){if(o){A({Title:"Confirm",Message:o,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(function(s){s!=="No"&&b(n)});return}b(n)};i.removeEventListener(t,a),i.addEventListener(t,a)})}function Y(){Pn(),Tn(),Bn()}function In(e){let i=new Map;for(let n in e)typeof e[n]=="function"&&i.set(n,e[n]);return i}var X={};w(X,{ByID:()=>Vn,ByName:()=>Hn,Call:()=>Nn,Plugin:()=>_n});window._wails=window._wails||{};window._wails.callResultHandler=zn;window._wails.callErrorHandler=kn;var y=0,Fn=l(d.Call,""),v=new Map;function Ln(){let e;do e=f();while(v.has(e));return e}function zn(e,i,n){let o=re(e);o&&o.resolve(n?JSON.parse(i):i)}function kn(e,i){let n=re(e);n&&n.reject(i)}function re(e){let i=v.get(e);return v.delete(e),i}function O(e,i={}){return new Promise((n,o)=>{let t=Ln();i["call-id"]=t,v.set(t,{resolve:n,reject:o}),Fn(e,i).catch(a=>{o(a),v.delete(t)})})}function Nn(e){return O(y,e)}function Hn(e,...i){if(typeof e!="string"||e.split(".").length!==3)throw new Error("CallByName requires a string in the format 'package.struct.method'");let[n,o,t]=e.split(".");return O(y,{packageName:n,structName:o,methodName:t,args:i})}function Vn(e,...i){return O(y,{methodID:e,args:i})}function _n(e,i,...n){return O(y,{packageName:"wails-plugins",structName:e,methodName:i,args:n})}window._wails=window._wails||{};window._wails.invoke=h;window.wails=window.wails||{};window.wails.Application=T;window.wails.Browser=B;window.wails.Call=X;window.wails.Clipboard=I;window.wails.Dialogs=G;window.wails.Events=j;window.wails.Flags=z;window.wails.Screens=N;window.wails.System=L;window.wails.Window=H;window.wails.WML=K;var ae=!1;document.addEventListener("DOMContentLoaded",function(){ae=!0,window._wails.invoke("wails:runtime:ready")});function Zn(e){ae||document.readyState==="complete"?e():document.addEventListener("DOMContentLoaded",e)}Zn(()=>{Y()});})(); From b325381ca079cf64485a1bc715d9eceb79bde7d9 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 17 Mar 2024 09:31:08 +1100 Subject: [PATCH 096/369] Normalise app/webview options Update deps --- v3/examples/binding/go.mod | 12 +++--- v3/examples/binding/go.sum | 4 ++ v3/examples/dev/go.mod | 8 ++-- v3/examples/dev/go.sum | 3 ++ v3/examples/frameless/go.mod | 12 +++--- v3/examples/frameless/go.sum | 4 ++ v3/examples/plugins/go.mod | 8 ++-- v3/examples/plugins/go.sum | 3 ++ v3/examples/server/go.mod | 8 ++-- v3/examples/server/go.sum | 3 ++ v3/examples/video/go.mod | 10 ++--- v3/examples/video/go.sum | 4 ++ v3/pkg/application/application_options.go | 45 +++++++++++++++++++++-- 13 files changed, 92 insertions(+), 32 deletions(-) diff --git a/v3/examples/binding/go.mod b/v3/examples/binding/go.mod index 963d59f479a..4e0bd8ded77 100644 --- a/v3/examples/binding/go.mod +++ b/v3/examples/binding/go.mod @@ -1,8 +1,8 @@ module binding -go 1.21.1 +go 1.22 -toolchain go1.21.4 +toolchain go1.22.0 require github.com/wailsapp/wails/v3 v3.0.0-alpha.0 @@ -11,7 +11,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.3.3 // indirect + github.com/cloudflare/circl v1.3.7 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/ebitengine/purego v0.4.0-alpha.4 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -39,11 +39,11 @@ require ( github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.19.0 // indirect + golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/binding/go.sum b/v3/examples/binding/go.sum index 53111bf10b4..604d980fdfe 100644 --- a/v3/examples/binding/go.sum +++ b/v3/examples/binding/go.sum @@ -14,6 +14,7 @@ github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3IS github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -112,6 +113,7 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -128,6 +130,7 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -152,6 +155,7 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= diff --git a/v3/examples/dev/go.mod b/v3/examples/dev/go.mod index 33fde4e41f8..3d38d3073b0 100644 --- a/v3/examples/dev/go.mod +++ b/v3/examples/dev/go.mod @@ -1,6 +1,6 @@ module changeme -go 1.21.1 +go 1.22 toolchain go1.22.0 @@ -40,10 +40,10 @@ require ( github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.19.0 // indirect + golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/dev/go.sum b/v3/examples/dev/go.sum index 817d628318a..8bc4ae557fd 100644 --- a/v3/examples/dev/go.sum +++ b/v3/examples/dev/go.sum @@ -131,6 +131,7 @@ golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -140,6 +141,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -160,6 +162,7 @@ golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= diff --git a/v3/examples/frameless/go.mod b/v3/examples/frameless/go.mod index 358eb760227..47718005736 100644 --- a/v3/examples/frameless/go.mod +++ b/v3/examples/frameless/go.mod @@ -1,8 +1,8 @@ module frameless -go 1.21.1 +go 1.22 -toolchain go1.21.5 +toolchain go1.22.0 require github.com/wailsapp/wails/v3 v3.0.0-alpha.0 @@ -11,7 +11,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.3.3 // indirect + github.com/cloudflare/circl v1.3.7 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/ebitengine/purego v0.4.0-alpha.4 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -39,11 +39,11 @@ require ( github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.19.0 // indirect + golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/frameless/go.sum b/v3/examples/frameless/go.sum index 476b71ea3bd..9843e8571f0 100644 --- a/v3/examples/frameless/go.sum +++ b/v3/examples/frameless/go.sum @@ -14,6 +14,7 @@ github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3IS github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -112,6 +113,7 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -128,6 +130,7 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -152,6 +155,7 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= diff --git a/v3/examples/plugins/go.mod b/v3/examples/plugins/go.mod index a31d9eb8a9a..232e375a8e9 100644 --- a/v3/examples/plugins/go.mod +++ b/v3/examples/plugins/go.mod @@ -1,6 +1,6 @@ module plugin_demo -go 1.21.1 +go 1.22 toolchain go1.22.0 @@ -44,11 +44,11 @@ require ( github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.19.0 // indirect + golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect lukechampine.com/uint128 v1.2.0 // indirect diff --git a/v3/examples/plugins/go.sum b/v3/examples/plugins/go.sum index cbc968c45ea..23a5a9343bb 100644 --- a/v3/examples/plugins/go.sum +++ b/v3/examples/plugins/go.sum @@ -142,6 +142,7 @@ golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= @@ -153,6 +154,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -175,6 +177,7 @@ golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= diff --git a/v3/examples/server/go.mod b/v3/examples/server/go.mod index 4ebf1edafab..6cc7e793f96 100644 --- a/v3/examples/server/go.mod +++ b/v3/examples/server/go.mod @@ -1,6 +1,6 @@ module server_demo -go 1.21.1 +go 1.22 toolchain go1.22.0 @@ -40,10 +40,10 @@ require ( github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.19.0 // indirect + golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/server/go.sum b/v3/examples/server/go.sum index 817d628318a..8bc4ae557fd 100644 --- a/v3/examples/server/go.sum +++ b/v3/examples/server/go.sum @@ -131,6 +131,7 @@ golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -140,6 +141,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -160,6 +162,7 @@ golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= diff --git a/v3/examples/video/go.mod b/v3/examples/video/go.mod index fed31b83339..47718005736 100644 --- a/v3/examples/video/go.mod +++ b/v3/examples/video/go.mod @@ -1,6 +1,6 @@ module frameless -go 1.21.1 +go 1.22 toolchain go1.22.0 @@ -11,7 +11,7 @@ require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.3.3 // indirect + github.com/cloudflare/circl v1.3.7 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/ebitengine/purego v0.4.0-alpha.4 // indirect github.com/emirpasic/gods v1.18.1 // indirect @@ -39,11 +39,11 @@ require ( github.com/wailsapp/go-webview2 v1.0.9 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.19.0 // indirect + golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/v3/examples/video/go.sum b/v3/examples/video/go.sum index 476b71ea3bd..9843e8571f0 100644 --- a/v3/examples/video/go.sum +++ b/v3/examples/video/go.sum @@ -14,6 +14,7 @@ github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3IS github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -112,6 +113,7 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -128,6 +130,7 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -152,6 +155,7 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= diff --git a/v3/pkg/application/application_options.go b/v3/pkg/application/application_options.go index c190d29d02c..26fc576cbf6 100644 --- a/v3/pkg/application/application_options.go +++ b/v3/pkg/application/application_options.go @@ -8,6 +8,19 @@ import ( "github.com/wailsapp/wails/v3/internal/assetserver" ) +// ActivationPolicy is the activation policy for the application. +type ActivationPolicy int + +const ( + // ActivationPolicyRegular is used for applications that have a user interface, + ActivationPolicyRegular ActivationPolicy = iota + // ActivationPolicyAccessory is used for applications that do not have a main window, + // such as system tray applications or background applications. + ActivationPolicyAccessory + ActivationPolicyProhibited +) + +// Options contains the options for the application type Options struct { // Name is the name of the application (used in the default about box) Name string @@ -19,13 +32,39 @@ type Options struct { Icon []byte // Mac is the Mac specific configuration for Mac builds - Mac MacOptions + Mac struct { + // ActivationPolicy is the activation policy for the application. Defaults to + // applicationActivationPolicyRegular. + ActivationPolicy ActivationPolicy + // If set to true, the application will terminate when the last window is closed. + ApplicationShouldTerminateAfterLastWindowClosed bool + } // Windows is the Windows specific configuration for Windows builds - Windows WindowsOptions + Windows struct { + + // WndProcInterceptor is a function that will be called for every message sent in the application. + // Use this to hook into the main message loop. This is useful for handling custom window messages. + // If `shouldReturn` is `true` then `returnCode` will be returned by the main message loop. + // If `shouldReturn` is `false` then returnCode will be ignored and the message will be processed by the main message loop. + WndProcInterceptor func(hwnd uintptr, msg uint32, wParam, lParam uintptr) (returnCode uintptr, shouldReturn bool) + + // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. + DisableQuitOnLastWindowClosed bool + + // Path where the WebView2 stores the user data. If empty %APPDATA%\[BinaryName.exe] will be used. + // If the path is not valid, a messagebox will be displayed with the error and the app will exit with error code. + WebviewUserDataPath string + + // Path to the directory with WebView2 executables. If empty WebView2 installed in the system will be used. + WebviewBrowserPath string + } // Linux is the Linux specific configuration for Linux builds - Linux LinuxOptions + Linux struct { + // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. + DisableQuitOnLastWindowClosed bool + } // Bind allows you to bind Go methods to the frontend. Bind []any From 4ab6352504654b8d7c6b5b9c9251199dfbe2104d Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 17 Mar 2024 20:56:54 +1100 Subject: [PATCH 097/369] Set default size for linux windows --- v3/pkg/application/linux_cgo.go | 4 ++++ v3/pkg/application/webview_window_linux.go | 1 + 2 files changed, 5 insertions(+) diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index a7ce902ae49..f888ff684e3 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -1021,6 +1021,10 @@ func (w *linuxWebviewWindow) setResizable(resizable bool) { C.gtk_window_set_resizable(w.gtkWindow(), gtkBool(resizable)) } +func (w *linuxWebviewWindow) setDefaultSize(width int, height int) { + C.gtk_window_set_default_size(w.gtkWindow(), C.gint(width), C.gint(height)) +} + func (w *linuxWebviewWindow) setBackgroundColour(colour RGBA) { rgba := C.GdkRGBA{C.double(colour.Red) / 255.0, C.double(colour.Green) / 255.0, C.double(colour.Blue) / 255.0, C.double(colour.Alpha) / 255.0} C.webkit_web_view_set_background_color((*C.WebKitWebView)(w.webview), &rgba) diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index a1a171e1b6e..28df0f4f3c7 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -230,6 +230,7 @@ func (w *linuxWebviewWindow) run() { w.parent.options.MaxHeight, ) } + w.setDefaultSize(w.parent.options.Width, w.parent.options.Height) w.setSize(w.parent.options.Width, w.parent.options.Height) w.setZoom(w.parent.options.Zoom) if w.parent.options.BackgroundType != BackgroundTypeSolid { From 98aff7778e6ca2e58809285d3adace07819de60f Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sun, 17 Mar 2024 21:09:20 +1100 Subject: [PATCH 098/369] Support ProgramName on linux --- v3/examples/frameless/go.sum | 15 +++--- v3/pkg/application/application_linux.go | 5 ++ v3/pkg/application/application_options.go | 53 +++++--------------- v3/pkg/application/linux_cgo.go | 6 +++ v3/pkg/application/webview_window_options.go | 9 ---- 5 files changed, 29 insertions(+), 59 deletions(-) diff --git a/v3/examples/frameless/go.sum b/v3/examples/frameless/go.sum index 9843e8571f0..dc9a40d99a6 100644 --- a/v3/examples/frameless/go.sum +++ b/v3/examples/frameless/go.sum @@ -12,8 +12,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= @@ -111,8 +111,7 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= @@ -128,8 +127,7 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -153,16 +151,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index 4db23d058c1..9ce6d3a1c62 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -186,6 +186,11 @@ func newPlatformApp(parent *App) *linuxApp { application: appNew(name), windowMap: map[windowPointer]uint{}, } + + if parent.options.Linux.ProgramName != "" { + setProgramName(parent.options.Linux.ProgramName) + } + return app } diff --git a/v3/pkg/application/application_options.go b/v3/pkg/application/application_options.go index 26fc576cbf6..e1d8c61cb60 100644 --- a/v3/pkg/application/application_options.go +++ b/v3/pkg/application/application_options.go @@ -8,18 +8,6 @@ import ( "github.com/wailsapp/wails/v3/internal/assetserver" ) -// ActivationPolicy is the activation policy for the application. -type ActivationPolicy int - -const ( - // ActivationPolicyRegular is used for applications that have a user interface, - ActivationPolicyRegular ActivationPolicy = iota - // ActivationPolicyAccessory is used for applications that do not have a main window, - // such as system tray applications or background applications. - ActivationPolicyAccessory - ActivationPolicyProhibited -) - // Options contains the options for the application type Options struct { // Name is the name of the application (used in the default about box) @@ -32,39 +20,13 @@ type Options struct { Icon []byte // Mac is the Mac specific configuration for Mac builds - Mac struct { - // ActivationPolicy is the activation policy for the application. Defaults to - // applicationActivationPolicyRegular. - ActivationPolicy ActivationPolicy - // If set to true, the application will terminate when the last window is closed. - ApplicationShouldTerminateAfterLastWindowClosed bool - } + Mac MacOptions // Windows is the Windows specific configuration for Windows builds - Windows struct { - - // WndProcInterceptor is a function that will be called for every message sent in the application. - // Use this to hook into the main message loop. This is useful for handling custom window messages. - // If `shouldReturn` is `true` then `returnCode` will be returned by the main message loop. - // If `shouldReturn` is `false` then returnCode will be ignored and the message will be processed by the main message loop. - WndProcInterceptor func(hwnd uintptr, msg uint32, wParam, lParam uintptr) (returnCode uintptr, shouldReturn bool) - - // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. - DisableQuitOnLastWindowClosed bool - - // Path where the WebView2 stores the user data. If empty %APPDATA%\[BinaryName.exe] will be used. - // If the path is not valid, a messagebox will be displayed with the error and the app will exit with error code. - WebviewUserDataPath string - - // Path to the directory with WebView2 executables. If empty WebView2 installed in the system will be used. - WebviewBrowserPath string - } + Windows WindowsOptions // Linux is the Linux specific configuration for Linux builds - Linux struct { - // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. - DisableQuitOnLastWindowClosed bool - } + Linux LinuxOptions // Bind allows you to bind Go methods to the frontend. Bind []any @@ -214,4 +176,13 @@ type WindowsOptions struct { type LinuxOptions struct { // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. DisableQuitOnLastWindowClosed bool + + // ProgramName is used to set the program's name for the window manager via GTK's g_set_prgname(). + //This name should not be localized. [see the docs] + // + //When a .desktop file is created this value helps with window grouping and desktop icons when the .desktop file's Name + //property differs form the executable's filename. + // + //[see the docs]: https://docs.gtk.org/glib/func.set_prgname.html + ProgramName string } diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go index f888ff684e3..8c7c2d27f95 100644 --- a/v3/pkg/application/linux_cgo.go +++ b/v3/pkg/application/linux_cgo.go @@ -332,6 +332,12 @@ func appNew(name string) pointer { return pointer(C.gtk_application_new(nameC, C.APPLICATION_DEFAULT_FLAGS)) } +func setProgramName(prgName string) { + cPrgName := C.CString(prgName) + defer C.free(unsafe.Pointer(cPrgName)) + C.g_set_prgname(cPrgName) +} + func appRun(app pointer) error { application := (*C.GApplication)(app) //TODO: Only set this if we configure it to do so diff --git a/v3/pkg/application/webview_window_options.go b/v3/pkg/application/webview_window_options.go index d84bce87443..2f220e3f1d1 100644 --- a/v3/pkg/application/webview_window_options.go +++ b/v3/pkg/application/webview_window_options.go @@ -513,13 +513,4 @@ type LinuxWindow struct { // Client code may override this behavior by passing a non-nil Options and set // WebviewGpuPolicy as needed. WebviewGpuPolicy WebviewGpuPolicy - - // ProgramName is used to set the program's name for the window manager via GTK's g_set_prgname(). - //This name should not be localized. [see the docs] - // - //When a .desktop file is created this value helps with window grouping and desktop icons when the .desktop file's Name - //property differs form the executable's filename. - // - //[see the docs]: https://docs.gtk.org/glib/func.set_prgname.html - ProgramName string } From c5bb4c740598f5149d580cfd271d59a884516473 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Mon, 18 Mar 2024 20:47:33 +1100 Subject: [PATCH 099/369] Refactor docs --- mkdocs-website/docs/en/API/application.md | 224 +- .../docs/en/API/application_dialogs.md | 67 + .../docs/en/API/application_events.md | 18 + .../docs/en/API/application_menu.md | 31 + .../docs/en/API/application_screens.md | 15 + .../docs/en/API/application_window.md | 67 + mkdocs-website/docs/en/API/fullapi.md | 4209 ----------------- mkdocs-website/docs/en/API/window.md | 12 +- mkdocs-website/docs/en/development/changes.md | 467 +- .../docs/en/development/changes_bindings.md | 87 + .../docs/en/development/changes_clipboard.md | 6 + .../en/development/changes_context_menus.md | 17 + .../docs/en/development/changes_dialogs.md | 25 + .../docs/en/development/changes_dragndrop.md | 8 + .../docs/en/development/changes_enums.md | 42 + .../docs/en/development/changes_events.md | 62 + .../docs/en/development/changes_logging.md | 11 + .../docs/en/development/changes_misc.md | 42 + .../docs/en/development/changes_plugins.md | 34 + .../docs/en/development/changes_systray.md | 13 + .../docs/en/development/changes_window.md | 36 + .../docs/en/development/changes_wml.md | 50 + mkdocs-website/docs/zh/API/application.md | 335 -- mkdocs-website/docs/zh/API/mainthread.md | 45 - mkdocs-website/docs/zh/API/menu.md | 66 - mkdocs-website/docs/zh/API/systray.md | 103 - mkdocs-website/docs/zh/API/window.md | 106 - mkdocs-website/docs/zh/changelog.md | 44 - mkdocs-website/docs/zh/development/changes.md | 402 -- .../docs/zh/development/introduction.md | 185 - mkdocs-website/docs/zh/development/status.md | 382 -- .../docs/zh/getting-started/feedback.md | 66 - .../docs/zh/getting-started/installation.md | 77 - .../docs/zh/getting-started/next-steps.md | 34 - mkdocs-website/docs/zh/index.md | 5 - mkdocs-website/docs/zh/roadmap.md | 41 - mkdocs-website/docs/zh/whats-new.md | 323 -- mkdocs-website/mkdocs.yml | 43 +- mkdocs-website/requirements.txt | Bin 2080 -> 1418 bytes 39 files changed, 683 insertions(+), 7117 deletions(-) create mode 100644 mkdocs-website/docs/en/API/application_dialogs.md create mode 100644 mkdocs-website/docs/en/API/application_events.md create mode 100644 mkdocs-website/docs/en/API/application_menu.md create mode 100644 mkdocs-website/docs/en/API/application_screens.md create mode 100644 mkdocs-website/docs/en/API/application_window.md delete mode 100644 mkdocs-website/docs/en/API/fullapi.md create mode 100644 mkdocs-website/docs/en/development/changes_bindings.md create mode 100644 mkdocs-website/docs/en/development/changes_clipboard.md create mode 100644 mkdocs-website/docs/en/development/changes_context_menus.md create mode 100644 mkdocs-website/docs/en/development/changes_dialogs.md create mode 100644 mkdocs-website/docs/en/development/changes_dragndrop.md create mode 100644 mkdocs-website/docs/en/development/changes_enums.md create mode 100644 mkdocs-website/docs/en/development/changes_events.md create mode 100644 mkdocs-website/docs/en/development/changes_logging.md create mode 100644 mkdocs-website/docs/en/development/changes_misc.md create mode 100644 mkdocs-website/docs/en/development/changes_plugins.md create mode 100644 mkdocs-website/docs/en/development/changes_systray.md create mode 100644 mkdocs-website/docs/en/development/changes_window.md create mode 100644 mkdocs-website/docs/en/development/changes_wml.md delete mode 100644 mkdocs-website/docs/zh/API/application.md delete mode 100644 mkdocs-website/docs/zh/API/mainthread.md delete mode 100644 mkdocs-website/docs/zh/API/menu.md delete mode 100644 mkdocs-website/docs/zh/API/systray.md delete mode 100644 mkdocs-website/docs/zh/API/window.md delete mode 100644 mkdocs-website/docs/zh/changelog.md delete mode 100644 mkdocs-website/docs/zh/development/changes.md delete mode 100644 mkdocs-website/docs/zh/development/introduction.md delete mode 100644 mkdocs-website/docs/zh/development/status.md delete mode 100644 mkdocs-website/docs/zh/getting-started/feedback.md delete mode 100644 mkdocs-website/docs/zh/getting-started/installation.md delete mode 100644 mkdocs-website/docs/zh/getting-started/next-steps.md delete mode 100644 mkdocs-website/docs/zh/index.md delete mode 100644 mkdocs-website/docs/zh/roadmap.md delete mode 100644 mkdocs-website/docs/zh/whats-new.md diff --git a/mkdocs-website/docs/en/API/application.md b/mkdocs-website/docs/en/API/application.md index 2d1a3c1cfbf..caddaf104a6 100644 --- a/mkdocs-website/docs/en/API/application.md +++ b/mkdocs-website/docs/en/API/application.md @@ -133,227 +133,19 @@ API: `Show()` app.Show() ``` -### NewWebviewWindow - -API: `NewWebviewWindow() *WebviewWindow` - -`NewWebviewWindow()` creates a new Webview window with default options, and -returns it. - -```go - // Create a new webview window - window := app.NewWebviewWindow() -``` - -### NewWebviewWindowWithOptions - -API: -`NewWebviewWindowWithOptions(windowOptions WebviewWindowOptions) *WebviewWindow` - -`NewWebviewWindowWithOptions()` creates a new webview window with custom -options. The newly created window is added to a map of windows managed by the -application. - -```go - // Create a new webview window with custom options - window := app.NewWebviewWindowWithOptions(WebviewWindowOptions{ - Name: "Main", - Title: "My Window", - Width: 800, - Height: 600, - }) -``` - -### OnWindowCreation - -API: `OnWindowCreation(callback func(window *WebviewWindow))` - -`OnWindowCreation()` registers a callback function to be called when a window is -created. - -```go - // Register a callback to be called when a window is created - app.OnWindowCreation(func(window *WebviewWindow) { - // Do something - }) -``` - -### GetWindowByName - -API: `GetWindowByName(name string) *WebviewWindow` - -`GetWindowByName()` fetches and returns a window with a specific name. - -```go - // Get a window by name - window := app.GetWindowByName("Main") -``` - -### CurrentWindow - -API: `CurrentWindow() *WebviewWindow` - -`CurrentWindow()` fetches and returns a pointer to the currently active window -in the application. If there is no window, it returns nil. - -```go - // Get the current window - window := app.CurrentWindow() -``` - -### RegisterContextMenu - -API: `RegisterContextMenu(name string, menu *Menu)` - -`RegisterContextMenu()` registers a context menu with a given name. This menu -can be used later in the application. - -```go - - // Create a new menu - ctxmenu := app.NewMenu() - - // Register the menu as a context menu - app.RegisterContextMenu("MyContextMenu", ctxmenu) -``` - -### SetMenu - -API: `SetMenu(menu *Menu)` - -`SetMenu()` sets the menu for the application. On Mac, this will be the global -menu. For Windows and Linux, this will be the default menu for any new window -created. - -```go - // Create a new menu - menu := app.NewMenu() - - // Set the menu for the application - app.SetMenu(menu) -``` - -### ShowAboutDialog - -API: `ShowAboutDialog()` - -`ShowAboutDialog()` shows an "About" dialog box. It can show the application's -name, description and icon. - -```go - // Show the about dialog - app.ShowAboutDialog() -``` - -### Info - -API: `InfoDialog()` - -`InfoDialog()` creates and returns a new instance of `MessageDialog` with an -`InfoDialogType`. This dialog is typically used to display informational -messages to the user. - -### Question - -API: `QuestionDialog()` - -`QuestionDialog()` creates and returns a new instance of `MessageDialog` with a -`QuestionDialogType`. This dialog is often used to ask a question to the user -and expect a response. - -### Warning - -API: `WarningDialog()` - -`WarningDialog()` creates and returns a new instance of `MessageDialog` with a -`WarningDialogType`. As the name suggests, this dialog is primarily used to -display warning messages to the user. - -### Error - -API: `ErrorDialog()` - -`ErrorDialog()` creates and returns a new instance of `MessageDialog` with an -`ErrorDialogType`. This dialog is designed to be used when you need to display -an error message to the user. - -### OpenFile - -API: `OpenFileDialog()` - -`OpenFileDialog()` creates and returns a new `OpenFileDialogStruct`. This dialog -prompts the user to select one or more files from their file system. - -### SaveFile - -API: `SaveFileDialog()` - -`SaveFileDialog()` creates and returns a new `SaveFileDialogStruct`. This dialog -prompts the user to choose a location on their file system where a file should -be saved. - -### OpenDirectory - -API: `OpenDirectoryDialog()` - -`OpenDirectoryDialog()` creates and returns a new instance of `MessageDialog` -with an `OpenDirectoryDialogType`. This dialog enables the user to choose a -directory from their file system. - -### On - -API: -`On(eventType events.ApplicationEventType, callback func(event *Event)) func()` - -`On()` registers an event listener for specific application events. The callback -function provided will be triggered when the corresponding event occurs. The -function returns a function that can be called to remove the listener. - -### RegisterHook - -API: -`RegisterHook(eventType events.ApplicationEventType, callback func(event *Event)) func()` - -`RegisterHook()` registers a callback to be run as a hook during specific -events. These hooks are run before listeners attached with `On()`. The function -returns a function that can be called to remove the hook. - -### GetPrimaryScreen - -API: `GetPrimaryScreen() (*Screen, error)` - -`GetPrimaryScreen()` returns the primary screen of the system. - -### GetScreens - -API: `GetScreens() ([]*Screen, error)` - -`GetScreens()` returns information about all screens attached to the system. - -This is a brief summary of the exported methods in the provided `App` struct. Do -note that for more detailed functionality or considerations, refer to the actual -Go code or further internal documentation. - -## Options - -```go title="application_options.go" --8<-- -../v3/pkg/application/options_application.go +./docs/en/API/application_window.md +./docs/en/API/application_menu.md +./docs/en/API/application_dialogs.md +./docs/en/API/application_events.md +./docs/en/API/application_screens.md --8<-- -``` - -### Windows Options -```go title="application_options_windows.go" ---8<-- -../v3/pkg/application/options_application_win.go ---8<-- -``` -### Mac Options +## Options -```go title="options_application_mac.go" +```go title="pkg/application/application_options.go" --8<-- -../v3/pkg/application/options_application_mac.go +../v3/pkg/application/application_options.go --8<-- ``` diff --git a/mkdocs-website/docs/en/API/application_dialogs.md b/mkdocs-website/docs/en/API/application_dialogs.md new file mode 100644 index 00000000000..9cd0980001d --- /dev/null +++ b/mkdocs-website/docs/en/API/application_dialogs.md @@ -0,0 +1,67 @@ + +### ShowAboutDialog + +API: `ShowAboutDialog()` + +`ShowAboutDialog()` shows an "About" dialog box. It can show the application's +name, description and icon. + +```go + // Show the about dialog + app.ShowAboutDialog() +``` + +### Info + +API: `InfoDialog()` + +`InfoDialog()` creates and returns a new instance of `MessageDialog` with an +`InfoDialogType`. This dialog is typically used to display informational +messages to the user. + +### Question + +API: `QuestionDialog()` + +`QuestionDialog()` creates and returns a new instance of `MessageDialog` with a +`QuestionDialogType`. This dialog is often used to ask a question to the user +and expect a response. + +### Warning + +API: `WarningDialog()` + +`WarningDialog()` creates and returns a new instance of `MessageDialog` with a +`WarningDialogType`. As the name suggests, this dialog is primarily used to +display warning messages to the user. + +### Error + +API: `ErrorDialog()` + +`ErrorDialog()` creates and returns a new instance of `MessageDialog` with an +`ErrorDialogType`. This dialog is designed to be used when you need to display +an error message to the user. + +### OpenFile + +API: `OpenFileDialog()` + +`OpenFileDialog()` creates and returns a new `OpenFileDialogStruct`. This dialog +prompts the user to select one or more files from their file system. + +### SaveFile + +API: `SaveFileDialog()` + +`SaveFileDialog()` creates and returns a new `SaveFileDialogStruct`. This dialog +prompts the user to choose a location on their file system where a file should +be saved. + +### OpenDirectory + +API: `OpenDirectoryDialog()` + +`OpenDirectoryDialog()` creates and returns a new instance of `MessageDialog` +with an `OpenDirectoryDialogType`. This dialog enables the user to choose a +directory from their file system. diff --git a/mkdocs-website/docs/en/API/application_events.md b/mkdocs-website/docs/en/API/application_events.md new file mode 100644 index 00000000000..3b2b73d073e --- /dev/null +++ b/mkdocs-website/docs/en/API/application_events.md @@ -0,0 +1,18 @@ + +### On + +API: +`On(eventType events.ApplicationEventType, callback func(event *Event)) func()` + +`On()` registers an event listener for specific application events. The callback +function provided will be triggered when the corresponding event occurs. The +function returns a function that can be called to remove the listener. + +### RegisterHook + +API: +`RegisterHook(eventType events.ApplicationEventType, callback func(event *Event)) func()` + +`RegisterHook()` registers a callback to be run as a hook during specific +events. These hooks are run before listeners attached with `On()`. The function +returns a function that can be called to remove the hook. diff --git a/mkdocs-website/docs/en/API/application_menu.md b/mkdocs-website/docs/en/API/application_menu.md new file mode 100644 index 00000000000..92242f9104a --- /dev/null +++ b/mkdocs-website/docs/en/API/application_menu.md @@ -0,0 +1,31 @@ +### RegisterContextMenu + +API: `RegisterContextMenu(name string, menu *Menu)` + +`RegisterContextMenu()` registers a context menu with a given name. This menu +can be used later in the application. + +```go + + // Create a new menu + ctxmenu := app.NewMenu() + + // Register the menu as a context menu + app.RegisterContextMenu("MyContextMenu", ctxmenu) +``` + +### SetMenu + +API: `SetMenu(menu *Menu)` + +`SetMenu()` sets the menu for the application. On Mac, this will be the global +menu. For Windows and Linux, this will be the default menu for any new window +created. + +```go + // Create a new menu + menu := app.NewMenu() + + // Set the menu for the application + app.SetMenu(menu) +``` diff --git a/mkdocs-website/docs/en/API/application_screens.md b/mkdocs-website/docs/en/API/application_screens.md new file mode 100644 index 00000000000..af057fbeaeb --- /dev/null +++ b/mkdocs-website/docs/en/API/application_screens.md @@ -0,0 +1,15 @@ +### GetPrimaryScreen + +API: `GetPrimaryScreen() (*Screen, error)` + +`GetPrimaryScreen()` returns the primary screen of the system. + +### GetScreens + +API: `GetScreens() ([]*Screen, error)` + +`GetScreens()` returns information about all screens attached to the system. + +This is a brief summary of the exported methods in the provided `App` struct. Do +note that for more detailed functionality or considerations, refer to the actual +Go code or further internal documentation. \ No newline at end of file diff --git a/mkdocs-website/docs/en/API/application_window.md b/mkdocs-website/docs/en/API/application_window.md new file mode 100644 index 00000000000..7af553791b0 --- /dev/null +++ b/mkdocs-website/docs/en/API/application_window.md @@ -0,0 +1,67 @@ +### NewWebviewWindow + +API: `NewWebviewWindow() *WebviewWindow` + +`NewWebviewWindow()` creates a new Webview window with default options, and +returns it. + +```go + // Create a new webview window + window := app.NewWebviewWindow() +``` + +### NewWebviewWindowWithOptions + +API: +`NewWebviewWindowWithOptions(windowOptions WebviewWindowOptions) *WebviewWindow` + +`NewWebviewWindowWithOptions()` creates a new webview window with custom +options. The newly created window is added to a map of windows managed by the +application. + +```go + // Create a new webview window with custom options + window := app.NewWebviewWindowWithOptions(WebviewWindowOptions{ + Name: "Main", + Title: "My Window", + Width: 800, + Height: 600, + }) +``` + +### OnWindowCreation + +API: `OnWindowCreation(callback func(window *WebviewWindow))` + +`OnWindowCreation()` registers a callback function to be called when a window is +created. + +```go + // Register a callback to be called when a window is created + app.OnWindowCreation(func(window *WebviewWindow) { + // Do something + }) +``` + +### GetWindowByName + +API: `GetWindowByName(name string) *WebviewWindow` + +`GetWindowByName()` fetches and returns a window with a specific name. + +```go + // Get a window by name + window := app.GetWindowByName("Main") +``` + +### CurrentWindow + +API: `CurrentWindow() *WebviewWindow` + +`CurrentWindow()` fetches and returns a pointer to the currently active window +in the application. If there is no window, it returns nil. + +```go + // Get the current window + window := app.CurrentWindow() +``` diff --git a/mkdocs-website/docs/en/API/fullapi.md b/mkdocs-website/docs/en/API/fullapi.md deleted file mode 100644 index 91663c6dc5e..00000000000 --- a/mkdocs-website/docs/en/API/fullapi.md +++ /dev/null @@ -1,4209 +0,0 @@ -# application - -```go -import "github.com/wailsapp/wails/v3/pkg/application" -``` - -## Index - -- [Constants](#constants) -- [Variables](#variables) -- [func DefaultLogger\(level slog.Level\) \*slog.Logger](#DefaultLogger) -- [func Fatal\(message string, args ...interface\{\}\)](#Fatal) -- [func InvokeAsync\(fn func\(\)\)](#InvokeAsync) -- [func InvokeSync\(fn func\(\)\)](#InvokeSync) -- [func InvokeSyncWithError\(fn func\(\) error\) \(err error\)](#InvokeSyncWithError) -- [func InvokeSyncWithResult\[T any\]\(fn func\(\) T\) \(res T\)](#InvokeSyncWithResult) -- [func InvokeSyncWithResultAndError\[T any\]\(fn func\(\) \(T, error\)\) \(res T, err error\)](#InvokeSyncWithResultAndError) -- [func NewIconFromResource\(instance w32.HINSTANCE, resId uint16\) \(w32.HICON, error\)](#NewIconFromResource) -- [func ScaleToDefaultDPI\(pixels int, dpi uint\) int](#ScaleToDefaultDPI) -- [func ScaleWithDPI\(pixels int, dpi uint\) int](#ScaleWithDPI) -- [type ActivationPolicy](#ActivationPolicy) -- [type App](#App) - - [func Get\(\) \*App](#Get) - - [func New\(appOptions Options\) \*App](#New) - - [func \(a \*App\) Capabilities\(\) capabilities.Capabilities](#App.Capabilities) - - [func \(a \*App\) Clipboard\(\) \*Clipboard](#App.Clipboard) - - [func \(a \*App\) CurrentWindow\(\) \*WebviewWindow](#App.CurrentWindow) - - [func \(a \*App\) GetPID\(\) int](#App.GetPID) - - [func \(a \*App\) GetPrimaryScreen\(\) \(\*Screen, error\)](#App.GetPrimaryScreen) - - [func \(a \*App\) GetScreens\(\) \(\[\]\*Screen, error\)](#App.GetScreens) - - [func \(a \*App\) GetWindowByName\(name string\) \*WebviewWindow](#App.GetWindowByName) - - [func \(a \*App\) Hide\(\)](#App.Hide) - - [func \(a \*App\) IsDarkMode\(\) bool](#App.IsDarkMode) - - [func \(a \*App\) NewMenu\(\) \*Menu](#App.NewMenu) - - [func \(a \*App\) NewSystemTray\(\) \*SystemTray](#App.NewSystemTray) - - [func \(a \*App\) NewWebviewWindow\(\) \*WebviewWindow](#App.NewWebviewWindow) - - [func \(a \*App\) NewWebviewWindowWithOptions\(windowOptions WebviewWindowOptions\) \*WebviewWindow](#App.NewWebviewWindowWithOptions) - - [func \(a \*App\) On\(eventType events.ApplicationEventType, callback func\(event \*Event\)\) func\(\)](#App.On) - - [func \(a \*App\) OnWindowCreation\(callback func\(window \*WebviewWindow\)\)](#App.OnWindowCreation) - - [func \(a \*App\) Quit\(\)](#App.Quit) - - [func \(a \*App\) RegisterContextMenu\(name string, menu \*Menu\)](#App.RegisterContextMenu) - - [func \(a \*App\) RegisterHook\(eventType events.ApplicationEventType, callback func\(event \*Event\)\) func\(\)](#App.RegisterHook) - - [func \(a \*App\) Run\(\) error](#App.Run) - - [func \(a \*App\) SetMenu\(menu \*Menu\)](#App.SetMenu) - - [func \(a \*App\) Show\(\)](#App.Show) - - [func \(a \*App\) ShowAboutDialog\(\)](#App.ShowAboutDialog) -- [type ApplicationEventContext](#ApplicationEventContext) - - [func \(c ApplicationEventContext\) IsDarkMode\(\) bool](#ApplicationEventContext.IsDarkMode) - - [func \(c ApplicationEventContext\) OpenedFiles\(\) \[\]string](#ApplicationEventContext.OpenedFiles) -- [type Args](#Args) - - [func \(a \*Args\) Bool\(s string\) \*bool](#Args.Bool) - - [func \(a \*Args\) Float64\(s string\) \*float64](#Args.Float64) - - [func \(a \*Args\) Int\(s string\) \*int](#Args.Int) - - [func \(a \*Args\) String\(key string\) \*string](#Args.String) - - [func \(a \*Args\) UInt\(s string\) \*uint](#Args.UInt) - - [func \(a \*Args\) UInt8\(s string\) \*uint8](#Args.UInt8) -- [type AssetOptions](#AssetOptions) -- [type BackdropType](#BackdropType) -- [type BackgroundType](#BackgroundType) -- [type Bindings](#Bindings) - - [func NewBindings\(structs \[\]any, aliases map\[uint32\]uint32\) \(\*Bindings, error\)](#NewBindings) - - [func \(b \*Bindings\) Add\(structPtr interface\{\}\) error](#Bindings.Add) - - [func \(b \*Bindings\) AddPlugins\(plugins map\[string\]Plugin\) error](#Bindings.AddPlugins) - - [func \(b \*Bindings\) GenerateID\(name string\) \(uint32, error\)](#Bindings.GenerateID) - - [func \(b \*Bindings\) Get\(options \*CallOptions\) \*BoundMethod](#Bindings.Get) - - [func \(b \*Bindings\) GetByID\(id uint32\) \*BoundMethod](#Bindings.GetByID) -- [type BoundMethod](#BoundMethod) - - [func \(b \*BoundMethod\) Call\(args \[\]interface\{\}\) \(returnValue interface\{\}, err error\)](#BoundMethod.Call) - - [func \(b \*BoundMethod\) String\(\) string](#BoundMethod.String) -- [type Button](#Button) - - [func \(b \*Button\) OnClick\(callback func\(\)\) \*Button](#Button.OnClick) - - [func \(b \*Button\) SetAsCancel\(\) \*Button](#Button.SetAsCancel) - - [func \(b \*Button\) SetAsDefault\(\) \*Button](#Button.SetAsDefault) -- [type CallOptions](#CallOptions) - - [func \(c CallOptions\) Name\(\) string](#CallOptions.Name) -- [type Clipboard](#Clipboard) - - [func \(c \*Clipboard\) SetText\(text string\) bool](#Clipboard.SetText) - - [func \(c \*Clipboard\) Text\(\) \(string, bool\)](#Clipboard.Text) -- [type Context](#Context) - - [func \(c \*Context\) ClickedMenuItem\(\) \*MenuItem](#Context.ClickedMenuItem) - - [func \(c \*Context\) ContextMenuData\(\) any](#Context.ContextMenuData) - - [func \(c \*Context\) IsChecked\(\) bool](#Context.IsChecked) -- [type ContextMenuData](#ContextMenuData) -- [type DialogType](#DialogType) -- [type Event](#Event) - - [func \(w \*Event\) Cancel\(\)](#Event.Cancel) - - [func \(w \*Event\) Context\(\) \*ApplicationEventContext](#Event.Context) -- [type EventListener](#EventListener) -- [type EventProcessor](#EventProcessor) - - [func NewWailsEventProcessor\(dispatchEventToWindows func\(\*WailsEvent\)\) \*EventProcessor](#NewWailsEventProcessor) - - [func \(e \*EventProcessor\) Emit\(thisEvent \*WailsEvent\)](#EventProcessor.Emit) - - [func \(e \*EventProcessor\) Off\(eventName string\)](#EventProcessor.Off) - - [func \(e \*EventProcessor\) OffAll\(\)](#EventProcessor.OffAll) - - [func \(e \*EventProcessor\) On\(eventName string, callback func\(event \*WailsEvent\)\) func\(\)](#EventProcessor.On) - - [func \(e \*EventProcessor\) OnMultiple\(eventName string, callback func\(event \*WailsEvent\), counter int\) func\(\)](#EventProcessor.OnMultiple) - - [func \(e \*EventProcessor\) Once\(eventName string, callback func\(event \*WailsEvent\)\) func\(\)](#EventProcessor.Once) - - [func \(e \*EventProcessor\) RegisterHook\(eventName string, callback func\(\*WailsEvent\)\) func\(\)](#EventProcessor.RegisterHook) -- [type FileFilter](#FileFilter) -- [type IconPosition](#IconPosition) -- [type MacAppearanceType](#MacAppearanceType) -- [type MacBackdrop](#MacBackdrop) -- [type MacOptions](#MacOptions) -- [type MacTitleBar](#MacTitleBar) -- [type MacToolbarStyle](#MacToolbarStyle) -- [type MacWindow](#MacWindow) -- [type Menu](#Menu) - - [func NewMenu\(\) \*Menu](#NewMenu) - - [func \(m \*Menu\) Add\(label string\) \*MenuItem](#Menu.Add) - - [func \(m \*Menu\) AddCheckbox\(label string, enabled bool\) \*MenuItem](#Menu.AddCheckbox) - - [func \(m \*Menu\) AddRadio\(label string, enabled bool\) \*MenuItem](#Menu.AddRadio) - - [func \(m \*Menu\) AddRole\(role Role\) \*Menu](#Menu.AddRole) - - [func \(m \*Menu\) AddSeparator\(\)](#Menu.AddSeparator) - - [func \(m \*Menu\) AddSubmenu\(s string\) \*Menu](#Menu.AddSubmenu) - - [func \(m \*Menu\) SetLabel\(label string\)](#Menu.SetLabel) - - [func \(m \*Menu\) Update\(\)](#Menu.Update) -- [type MenuItem](#MenuItem) - - [func \(m \*MenuItem\) Checked\(\) bool](#MenuItem.Checked) - - [func \(m \*MenuItem\) Enabled\(\) bool](#MenuItem.Enabled) - - [func \(m \*MenuItem\) Hidden\(\) bool](#MenuItem.Hidden) - - [func \(m \*MenuItem\) IsCheckbox\(\) bool](#MenuItem.IsCheckbox) - - [func \(m \*MenuItem\) IsRadio\(\) bool](#MenuItem.IsRadio) - - [func \(m \*MenuItem\) IsSeparator\(\) bool](#MenuItem.IsSeparator) - - [func \(m \*MenuItem\) IsSubmenu\(\) bool](#MenuItem.IsSubmenu) - - [func \(m \*MenuItem\) Label\(\) string](#MenuItem.Label) - - [func \(m \*MenuItem\) OnClick\(f func\(\*Context\)\) \*MenuItem](#MenuItem.OnClick) - - [func \(m \*MenuItem\) SetAccelerator\(shortcut string\) \*MenuItem](#MenuItem.SetAccelerator) - - [func \(m \*MenuItem\) SetChecked\(checked bool\) \*MenuItem](#MenuItem.SetChecked) - - [func \(m \*MenuItem\) SetEnabled\(enabled bool\) \*MenuItem](#MenuItem.SetEnabled) - - [func \(m \*MenuItem\) SetHidden\(hidden bool\) \*MenuItem](#MenuItem.SetHidden) - - [func \(m \*MenuItem\) SetLabel\(s string\) \*MenuItem](#MenuItem.SetLabel) - - [func \(m \*MenuItem\) SetTooltip\(s string\) \*MenuItem](#MenuItem.SetTooltip) - - [func \(m \*MenuItem\) Tooltip\(\) string](#MenuItem.Tooltip) -- [type MessageDialog](#MessageDialog) - - [func ErrorDialog\(\) \*MessageDialog](#ErrorDialog) - - [func InfoDialog\(\) \*MessageDialog](#InfoDialog) - - [func OpenDirectoryDialog\(\) \*MessageDialog](#OpenDirectoryDialog) - - [func QuestionDialog\(\) \*MessageDialog](#QuestionDialog) - - [func WarningDialog\(\) \*MessageDialog](#WarningDialog) - - [func \(d \*MessageDialog\) AddButton\(s string\) \*Button](#MessageDialog.AddButton) - - [func \(d \*MessageDialog\) AddButtons\(buttons \[\]\*Button\) \*MessageDialog](#MessageDialog.AddButtons) - - [func \(d \*MessageDialog\) AttachToWindow\(window \*WebviewWindow\) \*MessageDialog](#MessageDialog.AttachToWindow) - - [func \(d \*MessageDialog\) SetCancelButton\(button \*Button\) \*MessageDialog](#MessageDialog.SetCancelButton) - - [func \(d \*MessageDialog\) SetDefaultButton\(button \*Button\) \*MessageDialog](#MessageDialog.SetDefaultButton) - - [func \(d \*MessageDialog\) SetIcon\(icon \[\]byte\) \*MessageDialog](#MessageDialog.SetIcon) - - [func \(d \*MessageDialog\) SetMessage\(message string\) \*MessageDialog](#MessageDialog.SetMessage) - - [func \(d \*MessageDialog\) SetTitle\(title string\) \*MessageDialog](#MessageDialog.SetTitle) - - [func \(d \*MessageDialog\) Show\(\)](#MessageDialog.Show) -- [type MessageDialogOptions](#MessageDialogOptions) -- [type MessageProcessor](#MessageProcessor) - - [func NewMessageProcessor\(logger \*slog.Logger\) \*MessageProcessor](#NewMessageProcessor) - - [func \(m \*MessageProcessor\) Error\(message string, args ...any\)](#MessageProcessor.Error) - - [func \(m \*MessageProcessor\) HandleRuntimeCall\(rw http.ResponseWriter, r \*http.Request\)](#MessageProcessor.HandleRuntimeCall) - - [func \(m \*MessageProcessor\) HandleRuntimeCallWithIDs\(rw http.ResponseWriter, r \*http.Request\)](#MessageProcessor.HandleRuntimeCallWithIDs) - - [func \(m \*MessageProcessor\) Info\(message string, args ...any\)](#MessageProcessor.Info) -- [type Middleware](#Middleware) - - [func ChainMiddleware\(middleware ...Middleware\) Middleware](#ChainMiddleware) -- [type OpenFileDialogOptions](#OpenFileDialogOptions) -- [type OpenFileDialogStruct](#OpenFileDialogStruct) - - [func OpenFileDialog\(\) \*OpenFileDialogStruct](#OpenFileDialog) - - [func OpenFileDialogWithOptions\(options \*OpenFileDialogOptions\) \*OpenFileDialogStruct](#OpenFileDialogWithOptions) - - [func \(d \*OpenFileDialogStruct\) AddFilter\(displayName, pattern string\) \*OpenFileDialogStruct](#OpenFileDialogStruct.AddFilter) - - [func \(d \*OpenFileDialogStruct\) AllowsOtherFileTypes\(allowsOtherFileTypes bool\) \*OpenFileDialogStruct](#OpenFileDialogStruct.AllowsOtherFileTypes) - - [func \(d \*OpenFileDialogStruct\) AttachToWindow\(window \*WebviewWindow\) \*OpenFileDialogStruct](#OpenFileDialogStruct.AttachToWindow) - - [func \(d \*OpenFileDialogStruct\) CanChooseDirectories\(canChooseDirectories bool\) \*OpenFileDialogStruct](#OpenFileDialogStruct.CanChooseDirectories) - - [func \(d \*OpenFileDialogStruct\) CanChooseFiles\(canChooseFiles bool\) \*OpenFileDialogStruct](#OpenFileDialogStruct.CanChooseFiles) - - [func \(d \*OpenFileDialogStruct\) CanCreateDirectories\(canCreateDirectories bool\) \*OpenFileDialogStruct](#OpenFileDialogStruct.CanCreateDirectories) - - [func \(d \*OpenFileDialogStruct\) CanSelectHiddenExtension\(canSelectHiddenExtension bool\) \*OpenFileDialogStruct](#OpenFileDialogStruct.CanSelectHiddenExtension) - - [func \(d \*OpenFileDialogStruct\) HideExtension\(hideExtension bool\) \*OpenFileDialogStruct](#OpenFileDialogStruct.HideExtension) - - [func \(d \*OpenFileDialogStruct\) PromptForMultipleSelection\(\) \(\[\]string, error\)](#OpenFileDialogStruct.PromptForMultipleSelection) - - [func \(d \*OpenFileDialogStruct\) PromptForSingleSelection\(\) \(string, error\)](#OpenFileDialogStruct.PromptForSingleSelection) - - [func \(d \*OpenFileDialogStruct\) ResolvesAliases\(resolvesAliases bool\) \*OpenFileDialogStruct](#OpenFileDialogStruct.ResolvesAliases) - - [func \(d \*OpenFileDialogStruct\) SetButtonText\(text string\) \*OpenFileDialogStruct](#OpenFileDialogStruct.SetButtonText) - - [func \(d \*OpenFileDialogStruct\) SetDirectory\(directory string\) \*OpenFileDialogStruct](#OpenFileDialogStruct.SetDirectory) - - [func \(d \*OpenFileDialogStruct\) SetMessage\(message string\) \*OpenFileDialogStruct](#OpenFileDialogStruct.SetMessage) - - [func \(d \*OpenFileDialogStruct\) SetOptions\(options \*OpenFileDialogOptions\)](#OpenFileDialogStruct.SetOptions) - - [func \(d \*OpenFileDialogStruct\) SetTitle\(title string\) \*OpenFileDialogStruct](#OpenFileDialogStruct.SetTitle) - - [func \(d \*OpenFileDialogStruct\) ShowHiddenFiles\(showHiddenFiles bool\) \*OpenFileDialogStruct](#OpenFileDialogStruct.ShowHiddenFiles) - - [func \(d \*OpenFileDialogStruct\) TreatsFilePackagesAsDirectories\(treatsFilePackagesAsDirectories bool\) \*OpenFileDialogStruct](#OpenFileDialogStruct.TreatsFilePackagesAsDirectories) -- [type Options](#Options) -- [type Parameter](#Parameter) - - [func \(p \*Parameter\) IsError\(\) bool](#Parameter.IsError) - - [func \(p \*Parameter\) IsType\(typename string\) bool](#Parameter.IsType) -- [type Plugin](#Plugin) -- [type PluginCallOptions](#PluginCallOptions) -- [type PluginManager](#PluginManager) - - [func NewPluginManager\(plugins map\[string\]Plugin, assetServer \*assetserver.AssetServer\) \*PluginManager](#NewPluginManager) - - [func \(p \*PluginManager\) Init\(\) error](#PluginManager.Init) - - [func \(p \*PluginManager\) Shutdown\(\)](#PluginManager.Shutdown) -- [type PositionOptions](#PositionOptions) -- [type QueryParams](#QueryParams) - - [func \(qp QueryParams\) Args\(\) \(\*Args, error\)](#QueryParams.Args) - - [func \(qp QueryParams\) Bool\(key string\) \*bool](#QueryParams.Bool) - - [func \(qp QueryParams\) Float64\(key string\) \*float64](#QueryParams.Float64) - - [func \(qp QueryParams\) Int\(key string\) \*int](#QueryParams.Int) - - [func \(qp QueryParams\) String\(key string\) \*string](#QueryParams.String) - - [func \(qp QueryParams\) ToStruct\(str any\) error](#QueryParams.ToStruct) - - [func \(qp QueryParams\) UInt\(key string\) \*uint](#QueryParams.UInt) - - [func \(qp QueryParams\) UInt8\(key string\) \*uint8](#QueryParams.UInt8) -- [type RGBA](#RGBA) -- [type RadioGroup](#RadioGroup) - - [func \(r \*RadioGroup\) Add\(id int, item \*MenuItem\)](#RadioGroup.Add) - - [func \(r \*RadioGroup\) Bounds\(\) \(int, int\)](#RadioGroup.Bounds) - - [func \(r \*RadioGroup\) MenuID\(item \*MenuItem\) int](#RadioGroup.MenuID) -- [type RadioGroupMember](#RadioGroupMember) -- [type Rect](#Rect) -- [type Role](#Role) -- [type SaveFileDialogOptions](#SaveFileDialogOptions) -- [type SaveFileDialogStruct](#SaveFileDialogStruct) - - [func SaveFileDialog\(\) \*SaveFileDialogStruct](#SaveFileDialog) - - [func SaveFileDialogWithOptions\(s \*SaveFileDialogOptions\) \*SaveFileDialogStruct](#SaveFileDialogWithOptions) - - [func \(d \*SaveFileDialogStruct\) AddFilter\(displayName, pattern string\) \*SaveFileDialogStruct](#SaveFileDialogStruct.AddFilter) - - [func \(d \*SaveFileDialogStruct\) AllowsOtherFileTypes\(allowOtherFileTypes bool\) \*SaveFileDialogStruct](#SaveFileDialogStruct.AllowsOtherFileTypes) - - [func \(d \*SaveFileDialogStruct\) AttachToWindow\(window \*WebviewWindow\) \*SaveFileDialogStruct](#SaveFileDialogStruct.AttachToWindow) - - [func \(d \*SaveFileDialogStruct\) CanCreateDirectories\(canCreateDirectories bool\) \*SaveFileDialogStruct](#SaveFileDialogStruct.CanCreateDirectories) - - [func \(d \*SaveFileDialogStruct\) CanSelectHiddenExtension\(canSelectHiddenExtension bool\) \*SaveFileDialogStruct](#SaveFileDialogStruct.CanSelectHiddenExtension) - - [func \(d \*SaveFileDialogStruct\) HideExtension\(hideExtension bool\) \*SaveFileDialogStruct](#SaveFileDialogStruct.HideExtension) - - [func \(d \*SaveFileDialogStruct\) PromptForSingleSelection\(\) \(string, error\)](#SaveFileDialogStruct.PromptForSingleSelection) - - [func \(d \*SaveFileDialogStruct\) SetButtonText\(text string\) \*SaveFileDialogStruct](#SaveFileDialogStruct.SetButtonText) - - [func \(d \*SaveFileDialogStruct\) SetDirectory\(directory string\) \*SaveFileDialogStruct](#SaveFileDialogStruct.SetDirectory) - - [func \(d \*SaveFileDialogStruct\) SetFilename\(filename string\) \*SaveFileDialogStruct](#SaveFileDialogStruct.SetFilename) - - [func \(d \*SaveFileDialogStruct\) SetMessage\(message string\) \*SaveFileDialogStruct](#SaveFileDialogStruct.SetMessage) - - [func \(d \*SaveFileDialogStruct\) SetOptions\(options \*SaveFileDialogOptions\)](#SaveFileDialogStruct.SetOptions) - - [func \(d \*SaveFileDialogStruct\) ShowHiddenFiles\(showHiddenFiles bool\) \*SaveFileDialogStruct](#SaveFileDialogStruct.ShowHiddenFiles) - - [func \(d \*SaveFileDialogStruct\) TreatsFilePackagesAsDirectories\(treatsFilePackagesAsDirectories bool\) \*SaveFileDialogStruct](#SaveFileDialogStruct.TreatsFilePackagesAsDirectories) -- [type Screen](#Screen) -- [type Size](#Size) -- [type SystemTray](#SystemTray) - - [func \(s \*SystemTray\) AttachWindow\(window \*WebviewWindow\) \*SystemTray](#SystemTray.AttachWindow) - - [func \(s \*SystemTray\) Destroy\(\)](#SystemTray.Destroy) - - [func \(s \*SystemTray\) Label\(\) string](#SystemTray.Label) - - [func \(s \*SystemTray\) OnClick\(handler func\(\)\) \*SystemTray](#SystemTray.OnClick) - - [func \(s \*SystemTray\) OnDoubleClick\(handler func\(\)\) \*SystemTray](#SystemTray.OnDoubleClick) - - [func \(s \*SystemTray\) OnMouseEnter\(handler func\(\)\) \*SystemTray](#SystemTray.OnMouseEnter) - - [func \(s \*SystemTray\) OnMouseLeave\(handler func\(\)\) \*SystemTray](#SystemTray.OnMouseLeave) - - [func \(s \*SystemTray\) OnRightClick\(handler func\(\)\) \*SystemTray](#SystemTray.OnRightClick) - - [func \(s \*SystemTray\) OnRightDoubleClick\(handler func\(\)\) \*SystemTray](#SystemTray.OnRightDoubleClick) - - [func \(s \*SystemTray\) OpenMenu\(\)](#SystemTray.OpenMenu) - - [func \(s \*SystemTray\) PositionWindow\(window \*WebviewWindow, offset int\) error](#SystemTray.PositionWindow) - - [func \(s \*SystemTray\) SetDarkModeIcon\(icon \[\]byte\) \*SystemTray](#SystemTray.SetDarkModeIcon) - - [func \(s \*SystemTray\) SetIcon\(icon \[\]byte\) \*SystemTray](#SystemTray.SetIcon) - - [func \(s \*SystemTray\) SetIconPosition\(iconPosition int\) \*SystemTray](#SystemTray.SetIconPosition) - - [func \(s \*SystemTray\) SetLabel\(label string\)](#SystemTray.SetLabel) - - [func \(s \*SystemTray\) SetMenu\(menu \*Menu\) \*SystemTray](#SystemTray.SetMenu) - - [func \(s \*SystemTray\) SetTemplateIcon\(icon \[\]byte\) \*SystemTray](#SystemTray.SetTemplateIcon) - - [func \(s \*SystemTray\) WindowDebounce\(debounce time.Duration\) \*SystemTray](#SystemTray.WindowDebounce) - - [func \(s \*SystemTray\) WindowOffset\(offset int\) \*SystemTray](#SystemTray.WindowOffset) -- [type Theme](#Theme) -- [type ThemeSettings](#ThemeSettings) -- [type WailsEvent](#WailsEvent) - - [func \(e \*WailsEvent\) Cancel\(\)](#WailsEvent.Cancel) -- [type WebviewWindow](#WebviewWindow) - - [func \(w \*WebviewWindow\) AbsolutePosition\(\) \(int, int\)](#WebviewWindow.AbsolutePosition) - - [func \(w \*WebviewWindow\) Center\(\)](#WebviewWindow.Center) - - [func \(w \*WebviewWindow\) Close\(\)](#WebviewWindow.Close) - - [func \(w \*WebviewWindow\) Destroy\(\)](#WebviewWindow.Destroy) - - [func \(w \*WebviewWindow\) ExecJS\(js string\)](#WebviewWindow.ExecJS) - - [func \(w \*WebviewWindow\) Flash\(enabled bool\)](#WebviewWindow.Flash) - - [func \(w \*WebviewWindow\) Focus\(\)](#WebviewWindow.Focus) - - [func \(w \*WebviewWindow\) ForceReload\(\)](#WebviewWindow.ForceReload) - - [func \(w \*WebviewWindow\) Fullscreen\(\) \*WebviewWindow](#WebviewWindow.Fullscreen) - - [func \(w \*WebviewWindow\) GetScreen\(\) \(\*Screen, error\)](#WebviewWindow.GetScreen) - - [func \(w \*WebviewWindow\) GetZoom\(\) float64](#WebviewWindow.GetZoom) - - [func \(w \*WebviewWindow\) Height\(\) int](#WebviewWindow.Height) - - [func \(w \*WebviewWindow\) Hide\(\) \*WebviewWindow](#WebviewWindow.Hide) - - [func \(w \*WebviewWindow\) IsFocused\(\) bool](#WebviewWindow.IsFocused) - - [func \(w \*WebviewWindow\) IsFullscreen\(\) bool](#WebviewWindow.IsFullscreen) - - [func \(w \*WebviewWindow\) IsMaximised\(\) bool](#WebviewWindow.IsMaximised) - - [func \(w \*WebviewWindow\) IsMinimised\(\) bool](#WebviewWindow.IsMinimised) - - [func \(w \*WebviewWindow\) IsVisible\(\) bool](#WebviewWindow.IsVisible) - - [func \(w \*WebviewWindow\) Maximise\(\) \*WebviewWindow](#WebviewWindow.Maximise) - - [func \(w \*WebviewWindow\) Minimise\(\) \*WebviewWindow](#WebviewWindow.Minimise) - - [func \(w \*WebviewWindow\) Name\(\) string](#WebviewWindow.Name) - - [func \(w \*WebviewWindow\) NativeWindowHandle\(\) \(uintptr, error\)](#WebviewWindow.NativeWindowHandle) - - [func \(w \*WebviewWindow\) On\(eventType events.WindowEventType, callback func\(event \*WindowEvent\)\) func\(\)](#WebviewWindow.On) - - [func \(w \*WebviewWindow\) Print\(\) error](#WebviewWindow.Print) - - [func \(w \*WebviewWindow\) RegisterContextMenu\(name string, menu \*Menu\)](#WebviewWindow.RegisterContextMenu) - - [func \(w \*WebviewWindow\) RegisterHook\(eventType events.WindowEventType, callback func\(event \*WindowEvent\)\) func\(\)](#WebviewWindow.RegisterHook) - - [func \(w \*WebviewWindow\) RelativePosition\(\) \(int, int\)](#WebviewWindow.RelativePosition) - - [func \(w \*WebviewWindow\) Reload\(\)](#WebviewWindow.Reload) - - [func \(w \*WebviewWindow\) Resizable\(\) bool](#WebviewWindow.Resizable) - - [func \(w \*WebviewWindow\) Restore\(\)](#WebviewWindow.Restore) - - [func \(w \*WebviewWindow\) SetAbsolutePosition\(x int, y int\)](#WebviewWindow.SetAbsolutePosition) - - [func \(w \*WebviewWindow\) SetAlwaysOnTop\(b bool\) \*WebviewWindow](#WebviewWindow.SetAlwaysOnTop) - - [func \(w \*WebviewWindow\) SetBackgroundColour\(colour RGBA\) \*WebviewWindow](#WebviewWindow.SetBackgroundColour) - - [func \(w \*WebviewWindow\) SetEnabled\(enabled bool\)](#WebviewWindow.SetEnabled) - - [func \(w \*WebviewWindow\) SetFrameless\(frameless bool\) \*WebviewWindow](#WebviewWindow.SetFrameless) - - [func \(w \*WebviewWindow\) SetFullscreenButtonEnabled\(enabled bool\) \*WebviewWindow](#WebviewWindow.SetFullscreenButtonEnabled) - - [func \(w \*WebviewWindow\) SetHTML\(html string\) \*WebviewWindow](#WebviewWindow.SetHTML) - - [func \(w \*WebviewWindow\) SetMaxSize\(maxWidth, maxHeight int\) \*WebviewWindow](#WebviewWindow.SetMaxSize) - - [func \(w \*WebviewWindow\) SetMinSize\(minWidth, minHeight int\) \*WebviewWindow](#WebviewWindow.SetMinSize) - - [func \(w \*WebviewWindow\) SetRelativePosition\(x, y int\) \*WebviewWindow](#WebviewWindow.SetRelativePosition) - - [func \(w \*WebviewWindow\) SetResizable\(b bool\) \*WebviewWindow](#WebviewWindow.SetResizable) - - [func \(w \*WebviewWindow\) SetSize\(width, height int\) \*WebviewWindow](#WebviewWindow.SetSize) - - [func \(w \*WebviewWindow\) SetTitle\(title string\) \*WebviewWindow](#WebviewWindow.SetTitle) - - [func \(w \*WebviewWindow\) SetURL\(s string\) \*WebviewWindow](#WebviewWindow.SetURL) - - [func \(w \*WebviewWindow\) SetZoom\(magnification float64\) \*WebviewWindow](#WebviewWindow.SetZoom) - - [func \(w \*WebviewWindow\) Show\(\) \*WebviewWindow](#WebviewWindow.Show) - - [func \(w \*WebviewWindow\) Size\(\) \(int, int\)](#WebviewWindow.Size) - - [func \(w \*WebviewWindow\) ToggleDevTools\(\)](#WebviewWindow.ToggleDevTools) - - [func \(w \*WebviewWindow\) ToggleFullscreen\(\)](#WebviewWindow.ToggleFullscreen) - - [func \(w \*WebviewWindow\) ToggleMaximise\(\)](#WebviewWindow.ToggleMaximise) - - [func \(w \*WebviewWindow\) UnFullscreen\(\)](#WebviewWindow.UnFullscreen) - - [func \(w \*WebviewWindow\) UnMaximise\(\)](#WebviewWindow.UnMaximise) - - [func \(w \*WebviewWindow\) UnMinimise\(\)](#WebviewWindow.UnMinimise) - - [func \(w \*WebviewWindow\) Width\(\) int](#WebviewWindow.Width) - - [func \(w \*WebviewWindow\) Zoom\(\)](#WebviewWindow.Zoom) - - [func \(w \*WebviewWindow\) ZoomIn\(\)](#WebviewWindow.ZoomIn) - - [func \(w \*WebviewWindow\) ZoomOut\(\)](#WebviewWindow.ZoomOut) - - [func \(w \*WebviewWindow\) ZoomReset\(\) \*WebviewWindow](#WebviewWindow.ZoomReset) -- [type WebviewWindowOptions](#WebviewWindowOptions) -- [type Win32Menu](#Win32Menu) - - [func NewApplicationMenu\(parent w32.HWND, inputMenu \*Menu\) \*Win32Menu](#NewApplicationMenu) - - [func NewPopupMenu\(parent w32.HWND, inputMenu \*Menu\) \*Win32Menu](#NewPopupMenu) - - [func \(p \*Win32Menu\) Destroy\(\)](#Win32Menu.Destroy) - - [func \(p \*Win32Menu\) OnMenuClose\(fn func\(\)\)](#Win32Menu.OnMenuClose) - - [func \(p \*Win32Menu\) OnMenuOpen\(fn func\(\)\)](#Win32Menu.OnMenuOpen) - - [func \(p \*Win32Menu\) ProcessCommand\(cmdMsgID int\) bool](#Win32Menu.ProcessCommand) - - [func \(p \*Win32Menu\) ShowAt\(x int, y int\)](#Win32Menu.ShowAt) - - [func \(p \*Win32Menu\) ShowAtCursor\(\)](#Win32Menu.ShowAtCursor) - - [func \(p \*Win32Menu\) Update\(\)](#Win32Menu.Update) - - [func \(p \*Win32Menu\) UpdateMenuItem\(item \*MenuItem\)](#Win32Menu.UpdateMenuItem) -- [type WindowAttachConfig](#WindowAttachConfig) -- [type WindowEvent](#WindowEvent) - - [func NewWindowEvent\(\) \*WindowEvent](#NewWindowEvent) - - [func \(w \*WindowEvent\) Cancel\(\)](#WindowEvent.Cancel) - - [func \(w \*WindowEvent\) Context\(\) \*WindowEventContext](#WindowEvent.Context) -- [type WindowEventContext](#WindowEventContext) - - [func \(c WindowEventContext\) DroppedFiles\(\) \[\]string](#WindowEventContext.DroppedFiles) -- [type WindowEventListener](#WindowEventListener) -- [type WindowState](#WindowState) -- [type WindowsOptions](#WindowsOptions) -- [type WindowsWindow](#WindowsWindow) - -## Constants - - - -```go -const ( - ApplicationHide = 0 - ApplicationShow = 1 - ApplicationQuit = 2 -) -``` - - - -```go -const ( - ClipboardSetText = 0 - ClipboardText = 1 -) -``` - - - -```go -const ( - DialogInfo = 0 - DialogWarning = 1 - DialogError = 2 - DialogQuestion = 3 - DialogOpenFile = 4 - DialogSaveFile = 5 -) -``` - - - -```go -const ( - ScreensGetAll = 0 - ScreensGetPrimary = 1 - ScreensGetCurrent = 2 -) -``` - - - -```go -const ( - WindowCenter = 0 - WindowSetTitle = 1 - WindowFullscreen = 2 - WindowUnFullscreen = 3 - WindowSetSize = 4 - WindowSize = 5 - WindowSetMaxSize = 6 - WindowSetMinSize = 7 - WindowSetAlwaysOnTop = 8 - WindowSetRelativePosition = 9 - WindowRelativePosition = 10 - WindowScreen = 11 - WindowHide = 12 - WindowMaximise = 13 - WindowUnMaximise = 14 - WindowToggleMaximise = 15 - WindowMinimise = 16 - WindowUnMinimise = 17 - WindowRestore = 18 - WindowShow = 19 - WindowClose = 20 - WindowSetBackgroundColour = 21 - WindowSetResizable = 22 - WindowWidth = 23 - WindowHeight = 24 - WindowZoomIn = 25 - WindowZoomOut = 26 - WindowZoomReset = 27 - WindowGetZoomLevel = 28 - WindowSetZoomLevel = 29 -) -``` - - - -```go -const ( - NSImageNone = iota - NSImageOnly - NSImageLeft - NSImageRight - NSImageBelow - NSImageAbove - NSImageOverlaps - NSImageLeading - NSImageTrailing -) -``` - - - -```go -const ( - CallBinding = 0 -) -``` - - - -```go -const ( - ContextMenuOpen = 0 -) -``` - - - -```go -const ( - EventsEmit = 0 -) -``` - - - -```go -const ( - MenuItemMsgID = w32.WM_APP + 1024 -) -``` - - - -```go -const ( - SystemIsDarkMode = 0 -) -``` - - - -```go -const ( - WM_USER_SYSTRAY = w32.WM_USER + 1 -) -``` - -## Variables - -BuildInfo contains the build info for the application - -```go -var BuildInfo *debug.BuildInfo -``` - -BuildSettings contains the build settings for the -application - -```go -var BuildSettings map[string]string -``` - -MacTitleBarDefault results in the default Mac -MacTitleBar - -```go -var MacTitleBarDefault = MacTitleBar{ - AppearsTransparent: false, - Hide: false, - HideTitle: false, - FullSizeContent: false, - UseToolbar: false, - HideToolbarSeparator: false, -} -``` - -MacTitleBarHidden results in a hidden title bar -and a full size content window, yet the title bar still has the standard window -controls \(“traffic lights”\) in the top left. - -```go -var MacTitleBarHidden = MacTitleBar{ - AppearsTransparent: true, - Hide: false, - HideTitle: true, - FullSizeContent: true, - UseToolbar: false, - HideToolbarSeparator: false, -} -``` - -MacTitleBarHiddenInset results in a hidden -title bar with an alternative look where the traffic light buttons are slightly -more inset from the window edge. - -```go -var MacTitleBarHiddenInset = MacTitleBar{ - AppearsTransparent: true, - Hide: false, - HideTitle: true, - FullSizeContent: true, - UseToolbar: true, - HideToolbarSeparator: true, -} -``` - -MacTitleBarHiddenInsetUnified -results in a hidden title bar with an alternative look where the traffic light -buttons are even more inset from the window edge. - -```go -var MacTitleBarHiddenInsetUnified = MacTitleBar{ - AppearsTransparent: true, - Hide: false, - HideTitle: true, - FullSizeContent: true, - UseToolbar: true, - HideToolbarSeparator: true, - ToolbarStyle: MacToolbarStyleUnified, -} -``` - - - -```go -var VirtualKeyCodes = map[uint]string{ - 0x01: "lbutton", - 0x02: "rbutton", - 0x03: "cancel", - 0x04: "mbutton", - 0x05: "xbutton1", - 0x06: "xbutton2", - 0x08: "back", - 0x09: "tab", - 0x0C: "clear", - 0x0D: "return", - 0x10: "shift", - 0x11: "control", - 0x12: "menu", - 0x13: "pause", - 0x14: "capital", - 0x15: "kana", - 0x17: "junja", - 0x18: "final", - 0x19: "hanja", - 0x1B: "escape", - 0x1C: "convert", - 0x1D: "nonconvert", - 0x1E: "accept", - 0x1F: "modechange", - 0x20: "space", - 0x21: "prior", - 0x22: "next", - 0x23: "end", - 0x24: "home", - 0x25: "left", - 0x26: "up", - 0x27: "right", - 0x28: "down", - 0x29: "select", - 0x2A: "print", - 0x2B: "execute", - 0x2C: "snapshot", - 0x2D: "insert", - 0x2E: "delete", - 0x2F: "help", - 0x30: "0", - 0x31: "1", - 0x32: "2", - 0x33: "3", - 0x34: "4", - 0x35: "5", - 0x36: "6", - 0x37: "7", - 0x38: "8", - 0x39: "9", - 0x41: "a", - 0x42: "b", - 0x43: "c", - 0x44: "d", - 0x45: "e", - 0x46: "f", - 0x47: "g", - 0x48: "h", - 0x49: "i", - 0x4A: "j", - 0x4B: "k", - 0x4C: "l", - 0x4D: "m", - 0x4E: "n", - 0x4F: "o", - 0x50: "p", - 0x51: "q", - 0x52: "r", - 0x53: "s", - 0x54: "t", - 0x55: "u", - 0x56: "v", - 0x57: "w", - 0x58: "x", - 0x59: "y", - 0x5A: "z", - 0x5B: "lwin", - 0x5C: "rwin", - 0x5D: "apps", - 0x5F: "sleep", - 0x60: "numpad0", - 0x61: "numpad1", - 0x62: "numpad2", - 0x63: "numpad3", - 0x64: "numpad4", - 0x65: "numpad5", - 0x66: "numpad6", - 0x67: "numpad7", - 0x68: "numpad8", - 0x69: "numpad9", - 0x6A: "multiply", - 0x6B: "add", - 0x6C: "separator", - 0x6D: "subtract", - 0x6E: "decimal", - 0x6F: "divide", - 0x70: "f1", - 0x71: "f2", - 0x72: "f3", - 0x73: "f4", - 0x74: "f5", - 0x75: "f6", - 0x76: "f7", - 0x77: "f8", - 0x78: "f9", - 0x79: "f10", - 0x7A: "f11", - 0x7B: "f12", - 0x7C: "f13", - 0x7D: "f14", - 0x7E: "f15", - 0x7F: "f16", - 0x80: "f17", - 0x81: "f18", - 0x82: "f19", - 0x83: "f20", - 0x84: "f21", - 0x85: "f22", - 0x86: "f23", - 0x87: "f24", - 0x88: "navigation_view", - 0x89: "navigation_menu", - 0x8A: "navigation_up", - 0x8B: "navigation_down", - 0x8C: "navigation_left", - 0x8D: "navigation_right", - 0x8E: "navigation_accept", - 0x8F: "navigation_cancel", - 0x90: "numlock", - 0x91: "scroll", - 0x92: "oem_nec_equal", - 0x93: "oem_fj_masshou", - 0x94: "oem_fj_touroku", - 0x95: "oem_fj_loya", - 0x96: "oem_fj_roya", - 0xA0: "lshift", - 0xA1: "rshift", - 0xA2: "lcontrol", - 0xA3: "rcontrol", - 0xA4: "lmenu", - 0xA5: "rmenu", - 0xA6: "browser_back", - 0xA7: "browser_forward", - 0xA8: "browser_refresh", - 0xA9: "browser_stop", - 0xAA: "browser_search", - 0xAB: "browser_favorites", - 0xAC: "browser_home", - 0xAD: "volume_mute", - 0xAE: "volume_down", - 0xAF: "volume_up", - 0xB0: "media_next_track", - 0xB1: "media_prev_track", - 0xB2: "media_stop", - 0xB3: "media_play_pause", - 0xB4: "launch_mail", - 0xB5: "launch_media_select", - 0xB6: "launch_app1", - 0xB7: "launch_app2", - 0xBA: "oem_1", - 0xBB: "oem_plus", - 0xBC: "oem_comma", - 0xBD: "oem_minus", - 0xBE: "oem_period", - 0xBF: "oem_2", - 0xC0: "oem_3", - 0xC3: "gamepad_a", - 0xC4: "gamepad_b", - 0xC5: "gamepad_x", - 0xC6: "gamepad_y", - 0xC7: "gamepad_right_shoulder", - 0xC8: "gamepad_left_shoulder", - 0xC9: "gamepad_left_trigger", - 0xCA: "gamepad_right_trigger", - 0xCB: "gamepad_dpad_up", - 0xCC: "gamepad_dpad_down", - 0xCD: "gamepad_dpad_left", - 0xCE: "gamepad_dpad_right", - 0xCF: "gamepad_menu", - 0xD0: "gamepad_view", - 0xD1: "gamepad_left_thumbstick_button", - 0xD2: "gamepad_right_thumbstick_button", - 0xD3: "gamepad_left_thumbstick_up", - 0xD4: "gamepad_left_thumbstick_down", - 0xD5: "gamepad_left_thumbstick_right", - 0xD6: "gamepad_left_thumbstick_left", - 0xD7: "gamepad_right_thumbstick_up", - 0xD8: "gamepad_right_thumbstick_down", - 0xD9: "gamepad_right_thumbstick_right", - 0xDA: "gamepad_right_thumbstick_left", - 0xDB: "oem_4", - 0xDC: "oem_5", - 0xDD: "oem_6", - 0xDE: "oem_7", - 0xDF: "oem_8", - 0xE1: "oem_ax", - 0xE2: "oem_102", - 0xE3: "ico_help", - 0xE4: "ico_00", - 0xE5: "processkey", - 0xE6: "ico_clear", - 0xE7: "packet", - 0xE9: "oem_reset", - 0xEA: "oem_jump", - 0xEB: "oem_pa1", - 0xEC: "oem_pa2", - 0xED: "oem_pa3", - 0xEE: "oem_wsctrl", - 0xEF: "oem_cusel", - 0xF0: "oem_attn", - 0xF1: "oem_finish", - 0xF2: "oem_copy", - 0xF3: "oem_auto", - 0xF4: "oem_enlw", - 0xF5: "oem_backtab", - 0xF6: "attn", - 0xF7: "crsel", - 0xF8: "exsel", - 0xF9: "ereof", - 0xFA: "play", - 0xFB: "zoom", - 0xFC: "noname", - 0xFD: "pa1", - 0xFE: "oem_clear", -} -``` - - - -```go -var WebviewWindowDefaults = &WebviewWindowOptions{ - Title: "", - Width: 800, - Height: 600, - URL: "", - BackgroundColour: RGBA{ - Red: 255, - Green: 255, - Blue: 255, - Alpha: 255, - }, -} -``` - - - -## func [DefaultLogger](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/logger_windows.go#L14) - -```go -func DefaultLogger(level slog.Level) *slog.Logger -``` - - - -## func [Fatal](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/errors.go#L8) - -```go -func Fatal(message string, args ...interface{}) -``` - - - -## func [InvokeAsync](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/mainthread.go#L70) - -```go -func InvokeAsync(fn func()) -``` - - - -## func [InvokeSync](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/mainthread.go#L23) - -```go -func InvokeSync(fn func()) -``` - - - -## func [InvokeSyncWithError](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/mainthread.go#L46) - -```go -func InvokeSyncWithError(fn func() error) (err error) -``` - - - -## func [InvokeSyncWithResult](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/mainthread.go#L34) - -```go -func InvokeSyncWithResult[T any](fn func() T) (res T) -``` - - - -## func [InvokeSyncWithResultAndError](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/mainthread.go#L58) - -```go -func InvokeSyncWithResultAndError[T any](fn func() (T, error)) (res T, err error) -``` - - - -## func [NewIconFromResource](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window_windows.go#L1603) - -```go -func NewIconFromResource(instance w32.HINSTANCE, resId uint16) (w32.HICON, error) -``` - - - -## func [ScaleToDefaultDPI](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window_windows.go#L1599) - -```go -func ScaleToDefaultDPI(pixels int, dpi uint) int -``` - - - -## func [ScaleWithDPI](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window_windows.go#L1595) - -```go -func ScaleWithDPI(pixels int, dpi uint) int -``` - - - -## type [ActivationPolicy](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_application_mac.go#L4) - -ActivationPolicy is the activation policy for the application. - -```go -type ActivationPolicy int -``` - - - -```go -const ( - // ActivationPolicyRegular is used for applications that have a user interface, - ActivationPolicyRegular ActivationPolicy = iota - // ActivationPolicyAccessory is used for applications that do not have a main window, - // such as system tray applications or background applications. - ActivationPolicyAccessory - ActivationPolicyProhibited -) -``` - - - -## type [App](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L214-L269) - -```go -type App struct { - - // The main application menu - ApplicationMenu *Menu - - Events *EventProcessor - Logger *slog.Logger - // contains filtered or unexported fields -} -``` - - - -### func [Get](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L36) - -```go -func Get() *App -``` - - - -### func [New](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L40) - -```go -func New(appOptions Options) *App -``` - - - -### func \(\*App\) [Capabilities](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L300) - -```go -func (a *App) Capabilities() capabilities.Capabilities -``` - - - -### func \(\*App\) [Clipboard](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L639) - -```go -func (a *App) Clipboard() *Clipboard -``` - - - -### func \(\*App\) [CurrentWindow](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L563) - -```go -func (a *App) CurrentWindow() *WebviewWindow -``` - - - -### func \(\*App\) [GetPID](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L347) - -```go -func (a *App) GetPID() int -``` - - - -### func \(\*App\) [GetPrimaryScreen](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L631) - -```go -func (a *App) GetPrimaryScreen() (*Screen, error) -``` - - - -### func \(\*App\) [GetScreens](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L635) - -```go -func (a *App) GetScreens() ([]*Screen, error) -``` - - - -### func \(\*App\) [GetWindowByName](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L716) - -```go -func (a *App) GetWindowByName(name string) *WebviewWindow -``` - - - -### func \(\*App\) [Hide](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L686) - -```go -func (a *App) Hide() -``` - - - -### func \(\*App\) [IsDarkMode](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L679) - -```go -func (a *App) IsDarkMode() bool -``` - - - -### func \(\*App\) [NewMenu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menu.go#L98) - -```go -func (a *App) NewMenu() *Menu -``` - - - -### func \(\*App\) [NewSystemTray](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L397) - -```go -func (a *App) NewSystemTray() *SystemTray -``` - - - -### func \(\*App\) [NewWebviewWindow](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L343) - -```go -func (a *App) NewWebviewWindow() *WebviewWindow -``` - - - -### func \(\*App\) [NewWebviewWindowWithOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L379) - -```go -func (a *App) NewWebviewWindowWithOptions(windowOptions WebviewWindowOptions) *WebviewWindow -``` - - - -### func \(\*App\) [On](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L304) - -```go -func (a *App) On(eventType events.ApplicationEventType, callback func(event *Event)) func() -``` - - - -### func \(\*App\) [OnWindowCreation](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L712) - -```go -func (a *App) OnWindowCreation(callback func(window *WebviewWindow)) -``` - - - -### func \(\*App\) [Quit](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L573) - -```go -func (a *App) Quit() -``` - - - -### func \(\*App\) [RegisterContextMenu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L698) - -```go -func (a *App) RegisterContextMenu(name string, menu *Menu) -``` - - - -### func \(\*App\) [RegisterHook](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L327) - -```go -func (a *App) RegisterHook(eventType events.ApplicationEventType, callback func(event *Event)) func() -``` - -RegisterHook registers a hook for the given event type. Hooks are called before -the event listeners and can cancel the event. The returned function can be -called to remove the hook. - - - -### func \(\*App\) [Run](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L410) - -```go -func (a *App) Run() error -``` - - - -### func \(\*App\) [SetMenu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L591) - -```go -func (a *App) SetMenu(menu *Menu) -``` - - - -### func \(\*App\) [Show](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L692) - -```go -func (a *App) Show() -``` - - - -### func \(\*App\) [ShowAboutDialog](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L597) - -```go -func (a *App) ShowAboutDialog() -``` - - - -## type [ApplicationEventContext](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/context_application_event.go#L10-L13) - -```go -type ApplicationEventContext struct { - // contains filtered or unexported fields -} -``` - - - -### func \(ApplicationEventContext\) [IsDarkMode](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/context_application_event.go#L35) - -```go -func (c ApplicationEventContext) IsDarkMode() bool -``` - - - -### func \(ApplicationEventContext\) [OpenedFiles](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/context_application_event.go#L15) - -```go -func (c ApplicationEventContext) OpenedFiles() []string -``` - - - -## type [Args](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L109-L111) - -```go -type Args struct { - // contains filtered or unexported fields -} -``` - - - -### func \(\*Args\) [Bool](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L178) - -```go -func (a *Args) Bool(s string) *bool -``` - - - -### func \(\*Args\) [Float64](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L167) - -```go -func (a *Args) Float64(s string) *float64 -``` - - - -### func \(\*Args\) [Int](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L124) - -```go -func (a *Args) Int(s string) *int -``` - - - -### func \(\*Args\) [String](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L113) - -```go -func (a *Args) String(key string) *string -``` - - - -### func \(\*Args\) [UInt](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L157) - -```go -func (a *Args) UInt(s string) *uint -``` - - - -### func \(\*Args\) [UInt8](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L148) - -```go -func (a *Args) UInt8(s string) *uint8 -``` - - - -## type [AssetOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_application.go#L57-L87) - -AssetOptions defines the configuration of the AssetServer. - -```go -type AssetOptions struct { - // Handler which serves all the content to the WebView. - Handler http.Handler - - // Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default - // request handler dynamically, e.g. implement specialized Routing etc. - // The Middleware is called to build a new `http.Handler` used by the AssetSever and it also receives the default - // handler used by the AssetServer as an argument. - // - // This middleware injects itself before any of Wails internal middlewares. - // - // If not defined, the default AssetServer request chain is executed. - // - // Multiple Middlewares can be chained together with: - // ChainMiddleware(middleware ...Middleware) Middleware - Middleware Middleware - - // External URL can be set to a development server URL so that all requests are forwarded to it. This is useful - // when using a development server like `vite` or `snowpack` which serves the assets on a different port. - ExternalURL string -} -``` - - - -## type [BackdropType](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_webview_window_win.go#L5) - -```go -type BackdropType int32 -``` - - - -```go -const ( - Auto BackdropType = 0 - None BackdropType = 1 - Mica BackdropType = 2 - Acrylic BackdropType = 3 - Tabbed BackdropType = 4 -) -``` - - - -## type [BackgroundType](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_webview_window.go#L137) - -```go -type BackgroundType int -``` - - - -```go -const ( - BackgroundTypeSolid BackgroundType = iota - BackgroundTypeTransparent - BackgroundTypeTranslucent -) -``` - - - -## type [Bindings](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L76-L80) - -```go -type Bindings struct { - // contains filtered or unexported fields -} -``` - - - -### func [NewBindings](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L82) - -```go -func NewBindings(structs []any, aliases map[uint32]uint32) (*Bindings, error) -``` - - - -### func \(\*Bindings\) [Add](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L98) - -```go -func (b *Bindings) Add(structPtr interface{}) error -``` - -Add the given struct methods to the Bindings - - - -### func \(\*Bindings\) [AddPlugins](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L123) - -```go -func (b *Bindings) AddPlugins(plugins map[string]Plugin) error -``` - - - -### func \(\*Bindings\) [GenerateID](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L190) - -```go -func (b *Bindings) GenerateID(name string) (uint32, error) -``` - -GenerateID generates a unique ID for a binding - - - -### func \(\*Bindings\) [Get](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L161) - -```go -func (b *Bindings) Get(options *CallOptions) *BoundMethod -``` - -Get returns the bound method with the given name - - - -### func \(\*Bindings\) [GetByID](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L178) - -```go -func (b *Bindings) GetByID(id uint32) *BoundMethod -``` - -GetByID returns the bound method with the given ID - - - -## type [BoundMethod](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L64-L74) - -BoundMethod defines all the data related to a Go method that is bound to the -Wails application - -```go -type BoundMethod struct { - ID uint32 `json:"id"` - Name string `json:"name"` - Inputs []*Parameter `json:"inputs,omitempty"` - Outputs []*Parameter `json:"outputs,omitempty"` - Comments string `json:"comments,omitempty"` - Method reflect.Value `json:"-"` - PackageName string - StructName string - PackagePath string -} -``` - - - -### func \(\*BoundMethod\) [Call](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L298) - -```go -func (b *BoundMethod) Call(args []interface{}) (returnValue interface{}, err error) -``` - -Call will attempt to call this bound method with the given args - - - -### func \(\*BoundMethod\) [String](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L203) - -```go -func (b *BoundMethod) String() string -``` - - - -## type [Button](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L47-L52) - -```go -type Button struct { - Label string - IsCancel bool - IsDefault bool - Callback func() -} -``` - - - -### func \(\*Button\) [OnClick](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L54) - -```go -func (b *Button) OnClick(callback func()) *Button -``` - - - -### func \(\*Button\) [SetAsCancel](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L64) - -```go -func (b *Button) SetAsCancel() *Button -``` - - - -### func \(\*Button\) [SetAsDefault](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L59) - -```go -func (b *Button) SetAsDefault() *Button -``` - - - -## type [CallOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L13-L19) - -```go -type CallOptions struct { - MethodID uint32 `json:"methodID"` - PackageName string `json:"packageName"` - StructName string `json:"structName"` - MethodName string `json:"methodName"` - Args []any `json:"args"` -} -``` - - - -### func \(CallOptions\) [Name](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L21) - -```go -func (c CallOptions) Name() string -``` - - - -## type [Clipboard](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/clipboard.go#L8-L10) - -```go -type Clipboard struct { - // contains filtered or unexported fields -} -``` - - - -### func \(\*Clipboard\) [SetText](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/clipboard.go#L18) - -```go -func (c *Clipboard) SetText(text string) bool -``` - - - -### func \(\*Clipboard\) [Text](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/clipboard.go#L22) - -```go -func (c *Clipboard) Text() (string, bool) -``` - - - -## type [Context](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/context.go#L3-L6) - -```go -type Context struct { - // contains filtered or unexported fields -} -``` - - - -### func \(\*Context\) [ClickedMenuItem](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/context.go#L20) - -```go -func (c *Context) ClickedMenuItem() *MenuItem -``` - - - -### func \(\*Context\) [ContextMenuData](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/context.go#L35) - -```go -func (c *Context) ContextMenuData() any -``` - - - -### func \(\*Context\) [IsChecked](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/context.go#L28) - -```go -func (c *Context) IsChecked() bool -``` - - - -## type [ContextMenuData](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_contextmenu.go#L7-L12) - -```go -type ContextMenuData struct { - Id string `json:"id"` - X int `json:"x"` - Y int `json:"y"` - Data any `json:"data"` -} -``` - - - -## type [DialogType](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L8) - -```go -type DialogType int -``` - - - -```go -const ( - InfoDialogType DialogType = iota - QuestionDialogType - WarningDialogType - ErrorDialogType - OpenDirectoryDialogType -) -``` - - - -## type [Event](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L10-L14) - -```go -type Event struct { - Id uint - - Cancelled bool - // contains filtered or unexported fields -} -``` - - - -### func \(\*Event\) [Cancel](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L27) - -```go -func (w *Event) Cancel() -``` - - - -### func \(\*Event\) [Context](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L16) - -```go -func (w *Event) Context() *ApplicationEventContext -``` - - - -## type [EventListener](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L32-L34) - -```go -type EventListener struct { - // contains filtered or unexported fields -} -``` - - - -## type [EventProcessor](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L77-L84) - -EventProcessor handles custom events - -```go -type EventProcessor struct { - // contains filtered or unexported fields -} -``` - - - -### func [NewWailsEventProcessor](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L86) - -```go -func NewWailsEventProcessor(dispatchEventToWindows func(*WailsEvent)) *EventProcessor -``` - - - -### func \(\*EventProcessor\) [Emit](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L110) - -```go -func (e *EventProcessor) Emit(thisEvent *WailsEvent) -``` - -Emit sends an event to all listeners - - - -### func \(\*EventProcessor\) [Off](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L131) - -```go -func (e *EventProcessor) Off(eventName string) -``` - - - -### func \(\*EventProcessor\) [OffAll](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L135) - -```go -func (e *EventProcessor) OffAll() -``` - - - -### func \(\*EventProcessor\) [On](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L95) - -```go -func (e *EventProcessor) On(eventName string, callback func(event *WailsEvent)) func() -``` - -On is the equivalent of Javascript's \`addEventListener\` - - - -### func \(\*EventProcessor\) [OnMultiple](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L100) - -```go -func (e *EventProcessor) OnMultiple(eventName string, callback func(event *WailsEvent), counter int) func() -``` - -OnMultiple is the same as \`On\` but will unregister after \`count\` events - - - -### func \(\*EventProcessor\) [Once](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L105) - -```go -func (e *EventProcessor) Once(eventName string, callback func(event *WailsEvent)) func() -``` - -Once is the same as \`On\` but will unregister after the first event - - - -### func \(\*EventProcessor\) [RegisterHook](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L167) - -```go -func (e *EventProcessor) RegisterHook(eventName string, callback func(*WailsEvent)) func() -``` - -RegisterHook provides a means of registering methods to be called before -emitting the event - - - -## type [FileFilter](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L165-L168) - -```go -type FileFilter struct { - DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)" - Pattern string // semicolon separated list of extensions, EG: "*.jpg;*.png" -} -``` - - - -## type [IconPosition](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L12) - -```go -type IconPosition int -``` - - - -## type [MacAppearanceType](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_mac.go#L119) - -MacAppearanceType is a type of Appearance for Cocoa windows - -```go -type MacAppearanceType string -``` - - - -```go -const ( - // DefaultAppearance uses the default system value - DefaultAppearance MacAppearanceType = "" - // NSAppearanceNameAqua - The standard light system appearance. - NSAppearanceNameAqua MacAppearanceType = "NSAppearanceNameAqua" - // NSAppearanceNameDarkAqua - The standard dark system appearance. - NSAppearanceNameDarkAqua MacAppearanceType = "NSAppearanceNameDarkAqua" - // NSAppearanceNameVibrantLight - The light vibrant appearance - NSAppearanceNameVibrantLight MacAppearanceType = "NSAppearanceNameVibrantLight" - // NSAppearanceNameAccessibilityHighContrastAqua - A high-contrast version of the standard light system appearance. - NSAppearanceNameAccessibilityHighContrastAqua MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastAqua" - // NSAppearanceNameAccessibilityHighContrastDarkAqua - A high-contrast version of the standard dark system appearance. - NSAppearanceNameAccessibilityHighContrastDarkAqua MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastDarkAqua" - // NSAppearanceNameAccessibilityHighContrastVibrantLight - A high-contrast version of the light vibrant appearance. - NSAppearanceNameAccessibilityHighContrastVibrantLight MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastVibrantLight" - // NSAppearanceNameAccessibilityHighContrastVibrantDark - A high-contrast version of the dark vibrant appearance. - NSAppearanceNameAccessibilityHighContrastVibrantDark MacAppearanceType = "NSAppearanceNameAccessibilityHighContrastVibrantDark" -) -``` - - - -## type [MacBackdrop](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_mac.go#L6) - -MacBackdrop is the backdrop type for macOS - -```go -type MacBackdrop int -``` - - - -```go -const ( - // MacBackdropNormal - The default value. The window will have a normal opaque background. - MacBackdropNormal MacBackdrop = iota - // MacBackdropTransparent - The window will have a transparent background, with the content underneath it being visible - MacBackdropTransparent - // MacBackdropTranslucent - The window will have a translucent background, with the content underneath it being "fuzzy" or "frosted" - MacBackdropTranslucent -) -``` - - - -## type [MacOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_application_mac.go#L16-L22) - -MacOptions contains options for macOS applications. - -```go -type MacOptions struct { - // ActivationPolicy is the activation policy for the application. Defaults to - // applicationActivationPolicyRegular. - ActivationPolicy ActivationPolicy - // If set to true, the application will terminate when the last window is closed. - ApplicationShouldTerminateAfterLastWindowClosed bool -} -``` - - - -## type [MacTitleBar](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_mac.go#L54-L69) - -MacTitleBar contains options for the Mac titlebar - -```go -type MacTitleBar struct { - // AppearsTransparent will make the titlebar transparent - AppearsTransparent bool - // Hide will hide the titlebar - Hide bool - // HideTitle will hide the title - HideTitle bool - // FullSizeContent will extend the window content to the full size of the window - FullSizeContent bool - // UseToolbar will use a toolbar instead of a titlebar - UseToolbar bool - // HideToolbarSeparator will hide the toolbar separator - HideToolbarSeparator bool - // ShowToolbarWhenFullscreen will keep the toolbar visible when the window is in fullscreen mode - ShowToolbarWhenFullscreen bool - // ToolbarStyle is the style of toolbar to use - ToolbarStyle MacToolbarStyle -} -``` - - - -## type [MacToolbarStyle](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_mac.go#L18) - -MacToolbarStyle is the style of toolbar for macOS - -```go -type MacToolbarStyle int -``` - - - -```go -const ( - // MacToolbarStyleAutomatic - The default value. The style will be determined by the window's given configuration - MacToolbarStyleAutomatic MacToolbarStyle = iota - // MacToolbarStyleExpanded - The toolbar will appear below the window title - MacToolbarStyleExpanded - // MacToolbarStylePreference - The toolbar will appear below the window title and the items in the toolbar will attempt to have equal widths when possible - MacToolbarStylePreference - // MacToolbarStyleUnified - The window title will appear inline with the toolbar when visible - MacToolbarStyleUnified - // MacToolbarStyleUnifiedCompact - Same as MacToolbarStyleUnified, but with reduced margins in the toolbar allowing more focus to be on the contents of the window - MacToolbarStyleUnifiedCompact -) -``` - - - -## type [MacWindow](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_mac.go#L34-L51) - -MacWindow contains macOS specific options for Webview Windows - -```go -type MacWindow struct { - // Backdrop is the backdrop type for the window - Backdrop MacBackdrop - // DisableShadow will disable the window shadow - DisableShadow bool - // TitleBar contains options for the Mac titlebar - TitleBar MacTitleBar - // Appearance is the appearance type for the window - Appearance MacAppearanceType - // InvisibleTitleBarHeight defines the height of an invisible titlebar which responds to dragging - InvisibleTitleBarHeight int - // Maps events from platform specific to common event types - EventMapping map[events.WindowEventType]events.WindowEventType - - // EnableFraudulentWebsiteWarnings will enable warnings for fraudulent websites. - // Default: false - EnableFraudulentWebsiteWarnings bool -} -``` - - - -## type [Menu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menu.go#L7-L12) - -```go -type Menu struct { - // contains filtered or unexported fields -} -``` - - - -### func [NewMenu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menu.go#L14) - -```go -func NewMenu() *Menu -``` - - - -### func \(\*Menu\) [Add](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menu.go#L18) - -```go -func (m *Menu) Add(label string) *MenuItem -``` - - - -### func \(\*Menu\) [AddCheckbox](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menu.go#L29) - -```go -func (m *Menu) AddCheckbox(label string, enabled bool) *MenuItem -``` - - - -### func \(\*Menu\) [AddRadio](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menu.go#L35) - -```go -func (m *Menu) AddRadio(label string, enabled bool) *MenuItem -``` - - - -### func \(\*Menu\) [AddRole](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menu.go#L55) - -```go -func (m *Menu) AddRole(role Role) *Menu -``` - - - -### func \(\*Menu\) [AddSeparator](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menu.go#L24) - -```go -func (m *Menu) AddSeparator() -``` - - - -### func \(\*Menu\) [AddSubmenu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menu.go#L49) - -```go -func (m *Menu) AddSubmenu(s string) *Menu -``` - - - -### func \(\*Menu\) [SetLabel](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menu.go#L88) - -```go -func (m *Menu) SetLabel(label string) -``` - - - -### func \(\*Menu\) [Update](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menu.go#L41) - -```go -func (m *Menu) Update() -``` - - - -## type [MenuItem](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L45-L61) - -```go -type MenuItem struct { - // contains filtered or unexported fields -} -``` - - - -### func \(\*MenuItem\) [Checked](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L273) - -```go -func (m *MenuItem) Checked() bool -``` - - - -### func \(\*MenuItem\) [Enabled](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L310) - -```go -func (m *MenuItem) Enabled() bool -``` - - - -### func \(\*MenuItem\) [Hidden](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L293) - -```go -func (m *MenuItem) Hidden() bool -``` - - - -### func \(\*MenuItem\) [IsCheckbox](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L285) - -```go -func (m *MenuItem) IsCheckbox() bool -``` - - - -### func \(\*MenuItem\) [IsRadio](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L289) - -```go -func (m *MenuItem) IsRadio() bool -``` - - - -### func \(\*MenuItem\) [IsSeparator](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L277) - -```go -func (m *MenuItem) IsSeparator() bool -``` - - - -### func \(\*MenuItem\) [IsSubmenu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L281) - -```go -func (m *MenuItem) IsSubmenu() bool -``` - - - -### func \(\*MenuItem\) [Label](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L302) - -```go -func (m *MenuItem) Label() string -``` - - - -### func \(\*MenuItem\) [OnClick](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L297) - -```go -func (m *MenuItem) OnClick(f func(*Context)) *MenuItem -``` - - - -### func \(\*MenuItem\) [SetAccelerator](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L220) - -```go -func (m *MenuItem) SetAccelerator(shortcut string) *MenuItem -``` - - - -### func \(\*MenuItem\) [SetChecked](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L257) - -```go -func (m *MenuItem) SetChecked(checked bool) *MenuItem -``` - - - -### func \(\*MenuItem\) [SetEnabled](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L249) - -```go -func (m *MenuItem) SetEnabled(enabled bool) *MenuItem -``` - - - -### func \(\*MenuItem\) [SetHidden](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L265) - -```go -func (m *MenuItem) SetHidden(hidden bool) *MenuItem -``` - - - -### func \(\*MenuItem\) [SetLabel](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L241) - -```go -func (m *MenuItem) SetLabel(s string) *MenuItem -``` - - - -### func \(\*MenuItem\) [SetTooltip](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L233) - -```go -func (m *MenuItem) SetTooltip(s string) *MenuItem -``` - - - -### func \(\*MenuItem\) [Tooltip](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/menuitem.go#L306) - -```go -func (m *MenuItem) Tooltip() string -``` - - - -## type [MessageDialog](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L82-L87) - -```go -type MessageDialog struct { - MessageDialogOptions - // contains filtered or unexported fields -} -``` - - - -### func [ErrorDialog](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L615) - -```go -func ErrorDialog() *MessageDialog -``` - - - -### func [InfoDialog](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L603) - -```go -func InfoDialog() *MessageDialog -``` - - - -### func [OpenDirectoryDialog](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L619) - -```go -func OpenDirectoryDialog() *MessageDialog -``` - - - -### func [QuestionDialog](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L607) - -```go -func QuestionDialog() *MessageDialog -``` - - - -### func [WarningDialog](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L611) - -```go -func WarningDialog() *MessageDialog -``` - - - -### func \(\*MessageDialog\) [AddButton](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L122) - -```go -func (d *MessageDialog) AddButton(s string) *Button -``` - - - -### func \(\*MessageDialog\) [AddButtons](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L130) - -```go -func (d *MessageDialog) AddButtons(buttons []*Button) *MessageDialog -``` - - - -### func \(\*MessageDialog\) [AttachToWindow](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L135) - -```go -func (d *MessageDialog) AttachToWindow(window *WebviewWindow) *MessageDialog -``` - - - -### func \(\*MessageDialog\) [SetCancelButton](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L148) - -```go -func (d *MessageDialog) SetCancelButton(button *Button) *MessageDialog -``` - - - -### func \(\*MessageDialog\) [SetDefaultButton](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L140) - -```go -func (d *MessageDialog) SetDefaultButton(button *Button) *MessageDialog -``` - - - -### func \(\*MessageDialog\) [SetIcon](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L117) - -```go -func (d *MessageDialog) SetIcon(icon []byte) *MessageDialog -``` - - - -### func \(\*MessageDialog\) [SetMessage](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L156) - -```go -func (d *MessageDialog) SetMessage(message string) *MessageDialog -``` - - - -### func \(\*MessageDialog\) [SetTitle](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L105) - -```go -func (d *MessageDialog) SetTitle(title string) *MessageDialog -``` - - - -### func \(\*MessageDialog\) [Show](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L110) - -```go -func (d *MessageDialog) Show() -``` - - - -## type [MessageDialogOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L73-L80) - -```go -type MessageDialogOptions struct { - DialogType DialogType - Title string - Message string - Buttons []*Button - Icon []byte - // contains filtered or unexported fields -} -``` - - - -## type [MessageProcessor](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor.go#L26-L29) - -```go -type MessageProcessor struct { - // contains filtered or unexported fields -} -``` - - - -### func [NewMessageProcessor](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor.go#L31) - -```go -func NewMessageProcessor(logger *slog.Logger) *MessageProcessor -``` - - - -### func \(\*MessageProcessor\) [Error](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor.go#L147) - -```go -func (m *MessageProcessor) Error(message string, args ...any) -``` - - - -### func \(\*MessageProcessor\) [HandleRuntimeCall](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor.go#L65) - -```go -func (m *MessageProcessor) HandleRuntimeCall(rw http.ResponseWriter, r *http.Request) -``` - - - -### func \(\*MessageProcessor\) [HandleRuntimeCallWithIDs](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor.go#L104) - -```go -func (m *MessageProcessor) HandleRuntimeCallWithIDs(rw http.ResponseWriter, r *http.Request) -``` - - - -### func \(\*MessageProcessor\) [Info](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor.go#L151) - -```go -func (m *MessageProcessor) Info(message string, args ...any) -``` - - - -## type [Middleware](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_application.go#L92) - -Middleware defines HTTP middleware that can be applied to the AssetServer. The -handler passed as next is the next handler in the chain. One can decide to call -the next handler or implement a specialized handling. - -```go -type Middleware func(next http.Handler) http.Handler -``` - - - -### func [ChainMiddleware](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_application.go#L95) - -```go -func ChainMiddleware(middleware ...Middleware) Middleware -``` - -ChainMiddleware allows chaining multiple middlewares to one middleware. - - - -## type [OpenFileDialogOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L170-L188) - -```go -type OpenFileDialogOptions struct { - CanChooseDirectories bool - CanChooseFiles bool - CanCreateDirectories bool - ShowHiddenFiles bool - ResolvesAliases bool - AllowsMultipleSelection bool - HideExtension bool - CanSelectHiddenExtension bool - TreatsFilePackagesAsDirectories bool - AllowsOtherFileTypes bool - Filters []FileFilter - Window *WebviewWindow - - Title string - Message string - ButtonText string - Directory string -} -``` - - - -## type [OpenFileDialogStruct](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L190-L211) - -```go -type OpenFileDialogStruct struct { - // contains filtered or unexported fields -} -``` - - - -### func [OpenFileDialog](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L623) - -```go -func OpenFileDialog() *OpenFileDialogStruct -``` - - - -### func [OpenFileDialogWithOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L661) - -```go -func OpenFileDialogWithOptions(options *OpenFileDialogOptions) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [AddFilter](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L279) - -```go -func (d *OpenFileDialogStruct) AddFilter(displayName, pattern string) *OpenFileDialogStruct -``` - -AddFilter adds a filter to the dialog. The filter is a display name and a -semicolon separated list of extensions. EG: AddFilter\("Image Files", -"\*.jpg;\*.png"\) - - - -### func \(\*OpenFileDialogStruct\) [AllowsOtherFileTypes](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L228) - -```go -func (d *OpenFileDialogStruct) AllowsOtherFileTypes(allowsOtherFileTypes bool) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [AttachToWindow](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L248) - -```go -func (d *OpenFileDialogStruct) AttachToWindow(window *WebviewWindow) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [CanChooseDirectories](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L218) - -```go -func (d *OpenFileDialogStruct) CanChooseDirectories(canChooseDirectories bool) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [CanChooseFiles](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L213) - -```go -func (d *OpenFileDialogStruct) CanChooseFiles(canChooseFiles bool) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [CanCreateDirectories](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L223) - -```go -func (d *OpenFileDialogStruct) CanCreateDirectories(canCreateDirectories bool) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [CanSelectHiddenExtension](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L310) - -```go -func (d *OpenFileDialogStruct) CanSelectHiddenExtension(canSelectHiddenExtension bool) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [HideExtension](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L238) - -```go -func (d *OpenFileDialogStruct) HideExtension(hideExtension bool) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [PromptForMultipleSelection](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L287) - -```go -func (d *OpenFileDialogStruct) PromptForMultipleSelection() ([]string, error) -``` - - - -### func \(\*OpenFileDialogStruct\) [PromptForSingleSelection](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L263) - -```go -func (d *OpenFileDialogStruct) PromptForSingleSelection() (string, error) -``` - - - -### func \(\*OpenFileDialogStruct\) [ResolvesAliases](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L253) - -```go -func (d *OpenFileDialogStruct) ResolvesAliases(resolvesAliases bool) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [SetButtonText](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L300) - -```go -func (d *OpenFileDialogStruct) SetButtonText(text string) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [SetDirectory](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L305) - -```go -func (d *OpenFileDialogStruct) SetDirectory(directory string) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [SetMessage](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L295) - -```go -func (d *OpenFileDialogStruct) SetMessage(message string) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [SetOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L315) - -```go -func (d *OpenFileDialogStruct) SetOptions(options *OpenFileDialogOptions) -``` - - - -### func \(\*OpenFileDialogStruct\) [SetTitle](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L258) - -```go -func (d *OpenFileDialogStruct) SetTitle(title string) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [ShowHiddenFiles](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L233) - -```go -func (d *OpenFileDialogStruct) ShowHiddenFiles(showHiddenFiles bool) *OpenFileDialogStruct -``` - - - -### func \(\*OpenFileDialogStruct\) [TreatsFilePackagesAsDirectories](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L243) - -```go -func (d *OpenFileDialogStruct) TreatsFilePackagesAsDirectories(treatsFilePackagesAsDirectories bool) *OpenFileDialogStruct -``` - - - -## type [Options](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_application.go#L9-L54) - -```go -type Options struct { - // Name is the name of the application - Name string - - // Description is the description of the application (used in the default about box) - Description string - - // Icon is the icon of the application (used in the default about box) - Icon []byte - - // Mac is the Mac specific configuration for Mac builds - Mac MacOptions - - // Windows is the Windows specific configuration for Windows builds - Windows WindowsOptions - - // Bind allows you to bind Go methods to the frontend. - Bind []any - - // BindAliases allows you to specify alias IDs for your bound methods. - // Example: `BindAliases: map[uint32]uint32{1: 1411160069}` states that alias ID 1 maps to the Go method with ID 1411160069. - BindAliases map[uint32]uint32 - - // Logger i a slog.Logger instance used for logging Wails system messages (not application messages). - // If not defined, a default logger is used. - Logger *slog.Logger - - // LogLevel defines the log level of the Wails system logger. - LogLevel slog.Level - - // Assets are the application assets to be used. - Assets AssetOptions - - // Plugins is a map of plugins used by the application - Plugins map[string]Plugin - - // Flags are key value pairs that are available to the frontend. - // This is also used by Wails to provide information to the frontend. - Flags map[string]any - - // PanicHandler is a way to register a custom panic handler - PanicHandler func(any) - - // KeyBindings is a map of key bindings to functions - KeyBindings map[string]func(window *WebviewWindow) -} -``` - - - -## type [Parameter](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L38-L42) - -Parameter defines a Go method parameter - -```go -type Parameter struct { - Name string `json:"name,omitempty"` - TypeName string `json:"type"` - ReflectType reflect.Type -} -``` - - - -### func \(\*Parameter\) [IsError](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L58) - -```go -func (p *Parameter) IsError() bool -``` - -IsError returns true if the parameter type is an error - - - -### func \(\*Parameter\) [IsType](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L53) - -```go -func (p *Parameter) IsType(typename string) bool -``` - -IsType returns true if the given - - - -## type [Plugin](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/plugins.go#L5-L11) - -```go -type Plugin interface { - Name() string - Init() error - Shutdown() - CallableByJS() []string - InjectJS() string -} -``` - - - -## type [PluginCallOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/bindings.go#L25-L28) - -```go -type PluginCallOptions struct { - Name string `json:"name"` - Args []any `json:"args"` -} -``` - - - -## type [PluginManager](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/plugins.go#L13-L17) - -```go -type PluginManager struct { - // contains filtered or unexported fields -} -``` - - - -### func [NewPluginManager](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/plugins.go#L19) - -```go -func NewPluginManager(plugins map[string]Plugin, assetServer *assetserver.AssetServer) *PluginManager -``` - - - -### func \(\*PluginManager\) [Init](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/plugins.go#L27) - -```go -func (p *PluginManager) Init() error -``` - - - -### func \(\*PluginManager\) [Shutdown](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/plugins.go#L45) - -```go -func (p *PluginManager) Shutdown() -``` - - - -## type [PositionOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L41-L43) - -```go -type PositionOptions struct { - Buffer int -} -``` - - - -## type [QueryParams](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L9) - -```go -type QueryParams map[string][]string -``` - - - -### func \(QueryParams\) [Args](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L189) - -```go -func (qp QueryParams) Args() (*Args, error) -``` - - - -### func \(QueryParams\) [Bool](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L77) - -```go -func (qp QueryParams) Bool(key string) *bool -``` - - - -### func \(QueryParams\) [Float64](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L89) - -```go -func (qp QueryParams) Float64(key string) *float64 -``` - - - -### func \(QueryParams\) [Int](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L22) - -```go -func (qp QueryParams) Int(key string) *int -``` - - - -### func \(QueryParams\) [String](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L11) - -```go -func (qp QueryParams) String(key string) *string -``` - - - -### func \(QueryParams\) [ToStruct](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L101) - -```go -func (qp QueryParams) ToStruct(str any) error -``` - - - -### func \(QueryParams\) [UInt](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L55) - -```go -func (qp QueryParams) UInt(key string) *uint -``` - - - -### func \(QueryParams\) [UInt8](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/messageprocessor_params.go#L34) - -```go -func (qp QueryParams) UInt8(key string) *uint8 -``` - - - -## type [RGBA](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_webview_window.go#L133-L135) - -```go -type RGBA struct { - Red, Green, Blue, Alpha uint8 -} -``` - - - -## type [RadioGroup](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L17) - -```go -type RadioGroup []*RadioGroupMember -``` - - - -### func \(\*RadioGroup\) [Add](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L19) - -```go -func (r *RadioGroup) Add(id int, item *MenuItem) -``` - - - -### func \(\*RadioGroup\) [Bounds](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L26) - -```go -func (r *RadioGroup) Bounds() (int, int) -``` - - - -### func \(\*RadioGroup\) [MenuID](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L31) - -```go -func (r *RadioGroup) MenuID(item *MenuItem) int -``` - - - -## type [RadioGroupMember](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L12-L15) - -```go -type RadioGroupMember struct { - ID int - MenuItem *MenuItem -} -``` - - - -## type [Rect](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/screen.go#L16-L21) - -```go -type Rect struct { - X int - Y int - Width int - Height int -} -``` - - - -## type [Role](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/roles.go#L9) - -Role is a type to identify menu roles - -```go -type Role uint -``` - -These constants need to be kept in sync with -\`v2/internal/frontend/desktop/darwin/Role.h\` - -```go -const ( - NoRole Role = iota - AppMenu Role = iota - EditMenu Role = iota - ViewMenu Role = iota - WindowMenu Role = iota - ServicesMenu Role = iota - HelpMenu Role = iota - - Hide Role = iota - HideOthers Role = iota - UnHide Role = iota - About Role = iota - Undo Role = iota - Redo Role = iota - Cut Role = iota - Copy Role = iota - Paste Role = iota - PasteAndMatchStyle Role = iota - SelectAll Role = iota - Delete Role = iota - SpeechMenu Role = iota - Quit Role = iota - FileMenu Role = iota - Close Role = iota - Reload Role = iota - ForceReload Role = iota - ToggleDevTools Role = iota - ResetZoom Role = iota - ZoomIn Role = iota - ZoomOut Role = iota - ToggleFullscreen Role = iota - - Minimize Role = iota - Zoom Role = iota - FullScreen Role = iota -) -``` - - - -## type [SaveFileDialogOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L351-L365) - -```go -type SaveFileDialogOptions struct { - CanCreateDirectories bool - ShowHiddenFiles bool - CanSelectHiddenExtension bool - AllowOtherFileTypes bool - HideExtension bool - TreatsFilePackagesAsDirectories bool - Title string - Message string - Directory string - Filename string - ButtonText string - Filters []FileFilter - Window *WebviewWindow -} -``` - - - -## type [SaveFileDialogStruct](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L367-L385) - -```go -type SaveFileDialogStruct struct { - // contains filtered or unexported fields -} -``` - - - -### func [SaveFileDialog](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L627) - -```go -func SaveFileDialog() *SaveFileDialogStruct -``` - - - -### func [SaveFileDialogWithOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/application.go#L667) - -```go -func SaveFileDialogWithOptions(s *SaveFileDialogOptions) *SaveFileDialogStruct -``` - - - -### func \(\*SaveFileDialogStruct\) [AddFilter](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L409) - -```go -func (d *SaveFileDialogStruct) AddFilter(displayName, pattern string) *SaveFileDialogStruct -``` - -AddFilter adds a filter to the dialog. The filter is a display name and a -semicolon separated list of extensions. EG: AddFilter\("Image Files", -"\*.jpg;\*.png"\) - - - -### func \(\*SaveFileDialogStruct\) [AllowsOtherFileTypes](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L464) - -```go -func (d *SaveFileDialogStruct) AllowsOtherFileTypes(allowOtherFileTypes bool) *SaveFileDialogStruct -``` - - - -### func \(\*SaveFileDialogStruct\) [AttachToWindow](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L442) - -```go -func (d *SaveFileDialogStruct) AttachToWindow(window *WebviewWindow) *SaveFileDialogStruct -``` - - - -### func \(\*SaveFileDialogStruct\) [CanCreateDirectories](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L417) - -```go -func (d *SaveFileDialogStruct) CanCreateDirectories(canCreateDirectories bool) *SaveFileDialogStruct -``` - - - -### func \(\*SaveFileDialogStruct\) [CanSelectHiddenExtension](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L422) - -```go -func (d *SaveFileDialogStruct) CanSelectHiddenExtension(canSelectHiddenExtension bool) *SaveFileDialogStruct -``` - - - -### func \(\*SaveFileDialogStruct\) [HideExtension](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L469) - -```go -func (d *SaveFileDialogStruct) HideExtension(hideExtension bool) *SaveFileDialogStruct -``` - - - -### func \(\*SaveFileDialogStruct\) [PromptForSingleSelection](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L447) - -```go -func (d *SaveFileDialogStruct) PromptForSingleSelection() (string, error) -``` - - - -### func \(\*SaveFileDialogStruct\) [SetButtonText](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L454) - -```go -func (d *SaveFileDialogStruct) SetButtonText(text string) *SaveFileDialogStruct -``` - - - -### func \(\*SaveFileDialogStruct\) [SetDirectory](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L437) - -```go -func (d *SaveFileDialogStruct) SetDirectory(directory string) *SaveFileDialogStruct -``` - - - -### func \(\*SaveFileDialogStruct\) [SetFilename](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L459) - -```go -func (d *SaveFileDialogStruct) SetFilename(filename string) *SaveFileDialogStruct -``` - - - -### func \(\*SaveFileDialogStruct\) [SetMessage](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L432) - -```go -func (d *SaveFileDialogStruct) SetMessage(message string) *SaveFileDialogStruct -``` - - - -### func \(\*SaveFileDialogStruct\) [SetOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L391) - -```go -func (d *SaveFileDialogStruct) SetOptions(options *SaveFileDialogOptions) -``` - - - -### func \(\*SaveFileDialogStruct\) [ShowHiddenFiles](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L427) - -```go -func (d *SaveFileDialogStruct) ShowHiddenFiles(showHiddenFiles bool) *SaveFileDialogStruct -``` - - - -### func \(\*SaveFileDialogStruct\) [TreatsFilePackagesAsDirectories](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/dialogs.go#L474) - -```go -func (d *SaveFileDialogStruct) TreatsFilePackagesAsDirectories(treatsFilePackagesAsDirectories bool) *SaveFileDialogStruct -``` - - - -## type [Screen](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/screen.go#L3-L14) - -```go -type Screen struct { - ID string // A unique identifier for the display - Name string // The name of the display - Scale float32 // The scale factor of the display - X int // The x-coordinate of the top-left corner of the rectangle - Y int // The y-coordinate of the top-left corner of the rectangle - Size Size // The size of the display - Bounds Rect // The bounds of the display - WorkArea Rect // The work area of the display - IsPrimary bool // Whether this is the primary display - Rotation float32 // The rotation of the display -} -``` - - - -## type [Size](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/screen.go#L23-L26) - -```go -type Size struct { - Width int - Height int -} -``` - - - -## type [SystemTray](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L45-L66) - -```go -type SystemTray struct { - // contains filtered or unexported fields -} -``` - - - -### func \(\*SystemTray\) [AttachWindow](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L247) - -```go -func (s *SystemTray) AttachWindow(window *WebviewWindow) *SystemTray -``` - -AttachWindow attaches a window to the system tray. The window will be shown when -the system tray icon is clicked. The window will be hidden when the system tray -icon is clicked again, or when the window loses focus. - - - -### func \(\*SystemTray\) [Destroy](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L187) - -```go -func (s *SystemTray) Destroy() -``` - - - -### func \(\*SystemTray\) [Label](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L93) - -```go -func (s *SystemTray) Label() string -``` - - - -### func \(\*SystemTray\) [OnClick](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L194) - -```go -func (s *SystemTray) OnClick(handler func()) *SystemTray -``` - - - -### func \(\*SystemTray\) [OnDoubleClick](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L204) - -```go -func (s *SystemTray) OnDoubleClick(handler func()) *SystemTray -``` - - - -### func \(\*SystemTray\) [OnMouseEnter](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L214) - -```go -func (s *SystemTray) OnMouseEnter(handler func()) *SystemTray -``` - - - -### func \(\*SystemTray\) [OnMouseLeave](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L219) - -```go -func (s *SystemTray) OnMouseLeave(handler func()) *SystemTray -``` - - - -### func \(\*SystemTray\) [OnRightClick](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L199) - -```go -func (s *SystemTray) OnRightClick(handler func()) *SystemTray -``` - - - -### func \(\*SystemTray\) [OnRightDoubleClick](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L209) - -```go -func (s *SystemTray) OnRightDoubleClick(handler func()) *SystemTray -``` - - - -### func \(\*SystemTray\) [OpenMenu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L290) - -```go -func (s *SystemTray) OpenMenu() -``` - - - -### func \(\*SystemTray\) [PositionWindow](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L122) - -```go -func (s *SystemTray) PositionWindow(window *WebviewWindow, offset int) error -``` - - - -### func \(\*SystemTray\) [SetDarkModeIcon](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L142) - -```go -func (s *SystemTray) SetDarkModeIcon(icon []byte) *SystemTray -``` - - - -### func \(\*SystemTray\) [SetIcon](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L131) - -```go -func (s *SystemTray) SetIcon(icon []byte) *SystemTray -``` - - - -### func \(\*SystemTray\) [SetIconPosition](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L164) - -```go -func (s *SystemTray) SetIconPosition(iconPosition int) *SystemTray -``` - - - -### func \(\*SystemTray\) [SetLabel](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L83) - -```go -func (s *SystemTray) SetLabel(label string) -``` - - - -### func \(\*SystemTray\) [SetMenu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L153) - -```go -func (s *SystemTray) SetMenu(menu *Menu) *SystemTray -``` - - - -### func \(\*SystemTray\) [SetTemplateIcon](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L175) - -```go -func (s *SystemTray) SetTemplateIcon(icon []byte) *SystemTray -``` - - - -### func \(\*SystemTray\) [WindowDebounce](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L262) - -```go -func (s *SystemTray) WindowDebounce(debounce time.Duration) *SystemTray -``` - -WindowDebounce is used by Windows to indicate how long to wait before responding -to a mouse up event on the notification icon. This prevents the window from -being hidden and then immediately shown when the user clicks on the system tray -icon. See -https://stackoverflow.com/questions/4585283/alternate-showing-hiding-window-when-notify-icon-is-clicked - - - -### func \(\*SystemTray\) [WindowOffset](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L253) - -```go -func (s *SystemTray) WindowOffset(offset int) *SystemTray -``` - -WindowOffset sets the gap in pixels between the system tray and the window - - - -## type [Theme](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_webview_window_win.go#L79) - -```go -type Theme int -``` - - - -```go -const ( - // SystemDefault will use whatever the system theme is. The application will follow system theme changes. - SystemDefault Theme = 0 - // Dark Mode - Dark Theme = 1 - // Light Mode - Light Theme = 2 -) -``` - - - -## type [ThemeSettings](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_webview_window_win.go#L92-L105) - -ThemeSettings defines custom colours to use in dark or light mode. They may be -set using the hex values: 0x00BBGGRR - -```go -type ThemeSettings struct { - DarkModeTitleBar int32 - DarkModeTitleBarInactive int32 - DarkModeTitleText int32 - DarkModeTitleTextInactive int32 - DarkModeBorder int32 - DarkModeBorderInactive int32 - LightModeTitleBar int32 - LightModeTitleBarInactive int32 - LightModeTitleText int32 - LightModeTitleTextInactive int32 - LightModeBorder int32 - LightModeBorderInactive int32 -} -``` - - - -## type [WailsEvent](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L42-L47) - -```go -type WailsEvent struct { - Name string `json:"name"` - Data any `json:"data"` - Sender string `json:"sender"` - Cancelled bool -} -``` - - - -### func \(\*WailsEvent\) [Cancel](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/events.go#L49) - -```go -func (e *WailsEvent) Cancel() -``` - - - -## type [WebviewWindow](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L97-L116) - -```go -type WebviewWindow struct { - // contains filtered or unexported fields -} -``` - - - -### func \(\*WebviewWindow\) [AbsolutePosition](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L679) - -```go -func (w *WebviewWindow) AbsolutePosition() (int, int) -``` - -AbsolutePosition returns the absolute position of the window to the screen - - - -### func \(\*WebviewWindow\) [Center](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L580) - -```go -func (w *WebviewWindow) Center() -``` - -Center centers the window on the screen - - - -### func \(\*WebviewWindow\) [Close](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L770) - -```go -func (w *WebviewWindow) Close() -``` - -Close closes the window - - - -### func \(\*WebviewWindow\) [Destroy](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L690) - -```go -func (w *WebviewWindow) Destroy() -``` - - - -### func \(\*WebviewWindow\) [ExecJS](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L434) - -```go -func (w *WebviewWindow) ExecJS(js string) -``` - -ExecJS executes the given javascript in the context of the window. - - - -### func \(\*WebviewWindow\) [Flash](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L465) - -```go -func (w *WebviewWindow) Flash(enabled bool) -``` - -Flash flashes the window's taskbar button/icon. Windows only. - - - -### func \(\*WebviewWindow\) [Focus](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L1004) - -```go -func (w *WebviewWindow) Focus() -``` - - - -### func \(\*WebviewWindow\) [ForceReload](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L712) - -```go -func (w *WebviewWindow) ForceReload() -``` - -ForceReload forces the window to reload the page assets - - - -### func \(\*WebviewWindow\) [Fullscreen](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L442) - -```go -func (w *WebviewWindow) Fullscreen() *WebviewWindow -``` - -Fullscreen sets the window to fullscreen mode. Min/Max size constraints are -disabled. - - - -### func \(\*WebviewWindow\) [GetScreen](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L916) - -```go -func (w *WebviewWindow) GetScreen() (*Screen, error) -``` - -GetScreen returns the screen that the window is on - - - -### func \(\*WebviewWindow\) [GetZoom](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L346) - -```go -func (w *WebviewWindow) GetZoom() float64 -``` - -GetZoom returns the current zoom level of the window. - - - -### func \(\*WebviewWindow\) [Height](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L659) - -```go -func (w *WebviewWindow) Height() int -``` - -Height returns the height of the window - - - -### func \(\*WebviewWindow\) [Hide](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L315) - -```go -func (w *WebviewWindow) Hide() *WebviewWindow -``` - -Hide hides the window. - - - -### func \(\*WebviewWindow\) [IsFocused](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L511) - -```go -func (w *WebviewWindow) IsFocused() bool -``` - -IsFocused returns true if the window is currently focused - - - -### func \(\*WebviewWindow\) [IsFullscreen](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L519) - -```go -func (w *WebviewWindow) IsFullscreen() bool -``` - -IsFullscreen returns true if the window is fullscreen - - - -### func \(\*WebviewWindow\) [IsMaximised](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L491) - -```go -func (w *WebviewWindow) IsMaximised() bool -``` - -IsMaximised returns true if the window is maximised - - - -### func \(\*WebviewWindow\) [IsMinimised](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L475) - -```go -func (w *WebviewWindow) IsMinimised() bool -``` - -IsMinimised returns true if the window is minimised - - - -### func \(\*WebviewWindow\) [IsVisible](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L483) - -```go -func (w *WebviewWindow) IsVisible() bool -``` - -IsVisible returns true if the window is visible - - - -### func \(\*WebviewWindow\) [Maximise](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L822) - -```go -func (w *WebviewWindow) Maximise() *WebviewWindow -``` - -Maximise maximises the window. Min/Max size constraints are disabled. - - - -### func \(\*WebviewWindow\) [Minimise](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L809) - -```go -func (w *WebviewWindow) Minimise() *WebviewWindow -``` - -Minimise minimises the window. - - - -### func \(\*WebviewWindow\) [Name](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L234) - -```go -func (w *WebviewWindow) Name() string -``` - -Name returns the name of the window - - - -### func \(\*WebviewWindow\) [NativeWindowHandle](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L997) - -```go -func (w *WebviewWindow) NativeWindowHandle() (uintptr, error) -``` - -NativeWindowHandle returns the platform native window handle for the window. - - - -### func \(\*WebviewWindow\) [On](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L589) - -```go -func (w *WebviewWindow) On(eventType events.WindowEventType, callback func(event *WindowEvent)) func() -``` - -On registers a callback for the given window event - - - -### func \(\*WebviewWindow\) [Print](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L1027) - -```go -func (w *WebviewWindow) Print() error -``` - - - -### func \(\*WebviewWindow\) [RegisterContextMenu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L990) - -```go -func (w *WebviewWindow) RegisterContextMenu(name string, menu *Menu) -``` - -RegisterContextMenu registers a context menu and assigns it the given name. - - - -### func \(\*WebviewWindow\) [RegisterHook](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L609) - -```go -func (w *WebviewWindow) RegisterHook(eventType events.WindowEventType, callback func(event *WindowEvent)) func() -``` - -RegisterHook registers a hook for the given window event - - - -### func \(\*WebviewWindow\) [RelativePosition](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L667) - -```go -func (w *WebviewWindow) RelativePosition() (int, int) -``` - -RelativePosition returns the relative position of the window to the screen - - - -### func \(\*WebviewWindow\) [Reload](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L704) - -```go -func (w *WebviewWindow) Reload() -``` - -Reload reloads the page assets - - - -### func \(\*WebviewWindow\) [Resizable](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L365) - -```go -func (w *WebviewWindow) Resizable() bool -``` - -Resizable returns true if the window is resizable. - - - -### func \(\*WebviewWindow\) [Restore](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L871) - -```go -func (w *WebviewWindow) Restore() -``` - -Restore restores the window to its previous state if it was previously -minimised, maximised or fullscreen. - - - -### func \(\*WebviewWindow\) [SetAbsolutePosition](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L1043) - -```go -func (w *WebviewWindow) SetAbsolutePosition(x int, y int) -``` - - - -### func \(\*WebviewWindow\) [SetAlwaysOnTop](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L290) - -```go -func (w *WebviewWindow) SetAlwaysOnTop(b bool) *WebviewWindow -``` - -SetAlwaysOnTop sets the window to be always on top. - - - -### func \(\*WebviewWindow\) [SetBackgroundColour](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L527) - -```go -func (w *WebviewWindow) SetBackgroundColour(colour RGBA) *WebviewWindow -``` - -SetBackgroundColour sets the background colour of the window - - - -### func \(\*WebviewWindow\) [SetEnabled](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L1034) - -```go -func (w *WebviewWindow) SetEnabled(enabled bool) -``` - - - -### func \(\*WebviewWindow\) [SetFrameless](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L924) - -```go -func (w *WebviewWindow) SetFrameless(frameless bool) *WebviewWindow -``` - -SetFrameless removes the window frame and title bar - - - -### func \(\*WebviewWindow\) [SetFullscreenButtonEnabled](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L454) - -```go -func (w *WebviewWindow) SetFullscreenButtonEnabled(enabled bool) *WebviewWindow -``` - - - -### func \(\*WebviewWindow\) [SetHTML](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L786) - -```go -func (w *WebviewWindow) SetHTML(html string) *WebviewWindow -``` - -SetHTML sets the HTML of the window to the given html string. - - - -### func \(\*WebviewWindow\) [SetMaxSize](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L402) - -```go -func (w *WebviewWindow) SetMaxSize(maxWidth, maxHeight int) *WebviewWindow -``` - -SetMaxSize sets the maximum size of the window. - - - -### func \(\*WebviewWindow\) [SetMinSize](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L370) - -```go -func (w *WebviewWindow) SetMinSize(minWidth, minHeight int) *WebviewWindow -``` - -SetMinSize sets the minimum size of the window. - - - -### func \(\*WebviewWindow\) [SetRelativePosition](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L797) - -```go -func (w *WebviewWindow) SetRelativePosition(x, y int) *WebviewWindow -``` - -SetRelativePosition sets the position of the window. - - - -### func \(\*WebviewWindow\) [SetResizable](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L354) - -```go -func (w *WebviewWindow) SetResizable(b bool) *WebviewWindow -``` - -SetResizable sets whether the window is resizable. - - - -### func \(\*WebviewWindow\) [SetSize](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L239) - -```go -func (w *WebviewWindow) SetSize(width, height int) *WebviewWindow -``` - -SetSize sets the size of the window - - - -### func \(\*WebviewWindow\) [SetTitle](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L223) - -```go -func (w *WebviewWindow) SetTitle(title string) *WebviewWindow -``` - -SetTitle sets the title of the window - - - -### func \(\*WebviewWindow\) [SetURL](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L324) - -```go -func (w *WebviewWindow) SetURL(s string) *WebviewWindow -``` - - - -### func \(\*WebviewWindow\) [SetZoom](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L335) - -```go -func (w *WebviewWindow) SetZoom(magnification float64) *WebviewWindow -``` - -SetZoom sets the zoom level of the window. - - - -### func \(\*WebviewWindow\) [Show](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L301) - -```go -func (w *WebviewWindow) Show() *WebviewWindow -``` - -Show shows the window. - - - -### func \(\*WebviewWindow\) [Size](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L499) - -```go -func (w *WebviewWindow) Size() (int, int) -``` - -Size returns the size of the window - - - -### func \(\*WebviewWindow\) [ToggleDevTools](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L733) - -```go -func (w *WebviewWindow) ToggleDevTools() -``` - - - -### func \(\*WebviewWindow\) [ToggleFullscreen](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L720) - -```go -func (w *WebviewWindow) ToggleFullscreen() -``` - -ToggleFullscreen toggles the window between fullscreen and normal - - - -### func \(\*WebviewWindow\) [ToggleMaximise](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L720) - -```go -func (w *WebviewWindow) ToggleMaximise() -``` - -ToggleMaximise toggles the window between maximised and normal - - - -### func \(\*WebviewWindow\) [UnFullscreen](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L859) - -```go -func (w *WebviewWindow) UnFullscreen() -``` - -UnFullscreen un\-fullscreens the window. - - - -### func \(\*WebviewWindow\) [UnMaximise](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L847) - -```go -func (w *WebviewWindow) UnMaximise() -``` - -UnMaximise un\-maximises the window. - - - -### func \(\*WebviewWindow\) [UnMinimise](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L836) - -```go -func (w *WebviewWindow) UnMinimise() -``` - -UnMinimise un\-minimises the window. Min/Max size constraints are re\-enabled. - - - -### func \(\*WebviewWindow\) [Width](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L651) - -```go -func (w *WebviewWindow) Width() int -``` - -Width returns the width of the window - - - -### func \(\*WebviewWindow\) [Zoom](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L777) - -```go -func (w *WebviewWindow) Zoom() -``` - - - -### func \(\*WebviewWindow\) [ZoomIn](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L751) - -```go -func (w *WebviewWindow) ZoomIn() -``` - -ZoomIn increases the zoom level of the webview content - - - -### func \(\*WebviewWindow\) [ZoomOut](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L761) - -```go -func (w *WebviewWindow) ZoomOut() -``` - -ZoomOut decreases the zoom level of the webview content - - - -### func \(\*WebviewWindow\) [ZoomReset](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L741) - -```go -func (w *WebviewWindow) ZoomReset() *WebviewWindow -``` - -ZoomReset resets the zoom level of the webview content to 100% - - - -## type [WebviewWindowOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_webview_window.go#L12-L118) - -```go -type WebviewWindowOptions struct { - // Name is a unique identifier that can be given to a window. - Name string - - // Title is the title of the window. - Title string - - // Width is the starting width of the window. - Width int - - // Height is the starting height of the window. - Height int - - // AlwaysOnTop will make the window float above other windows. - AlwaysOnTop bool - - // URL is the URL to load in the window. - URL string - - // DisableResize will disable the ability to resize the window. - DisableResize bool - - // Frameless will remove the window frame. - Frameless bool - - // MinWidth is the minimum width of the window. - MinWidth int - - // MinHeight is the minimum height of the window. - MinHeight int - - // MaxWidth is the maximum width of the window. - MaxWidth int - - // MaxHeight is the maximum height of the window. - MaxHeight int - - // StartState indicates the state of the window when it is first shown. - // Default: WindowStateNormal - StartState WindowState - - // Centered will center the window on the screen. - Centered bool - - // BackgroundType is the type of background to use for the window. - // Default: BackgroundTypeSolid - BackgroundType BackgroundType - - // BackgroundColour is the colour to use for the window background. - BackgroundColour RGBA - - // HTML is the HTML to load in the window. - HTML string - - // JS is the JavaScript to load in the window. - JS string - - // CSS is the CSS to load in the window. - CSS string - - // X is the starting X position of the window. - X int - - // Y is the starting Y position of the window. - Y int - - // TransparentTitlebar will make the titlebar transparent. - // TODO: Move to mac window options - FullscreenButtonEnabled bool - - // Hidden will hide the window when it is first created. - Hidden bool - - // Zoom is the zoom level of the window. - Zoom float64 - - // ZoomControlEnabled will enable the zoom control. - ZoomControlEnabled bool - - // EnableDragAndDrop will enable drag and drop. - EnableDragAndDrop bool - - // OpenInspectorOnStartup will open the inspector when the window is first shown. - OpenInspectorOnStartup bool - - // Mac options - Mac MacWindow - - // Windows options - Windows WindowsWindow - - // Focused indicates the window should be focused when initially shown - Focused bool - - // ShouldClose is called when the window is about to close. - // Return true to allow the window to close, or false to prevent it from closing. - ShouldClose func(window *WebviewWindow) bool - - // If true, the window's devtools will be available (default true in builds without the `production` build tag) - DevToolsEnabled bool - - // If true, the window's default context menu will be disabled (default false) - DefaultContextMenuDisabled bool - - // KeyBindings is a map of key bindings to functions - KeyBindings map[string]func(window *WebviewWindow) -} -``` - - - -## type [Win32Menu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L40-L51) - -```go -type Win32Menu struct { - // contains filtered or unexported fields -} -``` - - - -### func [NewApplicationMenu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L143) - -```go -func NewApplicationMenu(parent w32.HWND, inputMenu *Menu) *Win32Menu -``` - - - -### func [NewPopupMenu](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L132) - -```go -func NewPopupMenu(parent w32.HWND, inputMenu *Menu) *Win32Menu -``` - - - -### func \(\*Win32Menu\) [Destroy](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L200) - -```go -func (p *Win32Menu) Destroy() -``` - - - -### func \(\*Win32Menu\) [OnMenuClose](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L241) - -```go -func (p *Win32Menu) OnMenuClose(fn func()) -``` - - - -### func \(\*Win32Menu\) [OnMenuOpen](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L237) - -```go -func (p *Win32Menu) OnMenuOpen(fn func()) -``` - - - -### func \(\*Win32Menu\) [ProcessCommand](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L185) - -```go -func (p *Win32Menu) ProcessCommand(cmdMsgID int) bool -``` - - - -### func \(\*Win32Menu\) [ShowAt](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L154) - -```go -func (p *Win32Menu) ShowAt(x int, y int) -``` - - - -### func \(\*Win32Menu\) [ShowAtCursor](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L176) - -```go -func (p *Win32Menu) ShowAtCursor() -``` - - - -### func \(\*Win32Menu\) [Update](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L124) - -```go -func (p *Win32Menu) Update() -``` - - - -### func \(\*Win32Menu\) [UpdateMenuItem](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/popupmenu_windows.go#L204) - -```go -func (p *Win32Menu) UpdateMenuItem(item *MenuItem) -``` - - - -## type [WindowAttachConfig](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/systemtray.go#L224-L243) - -```go -type WindowAttachConfig struct { - // Window is the window to attach to the system tray. If it's null, the request to attach will be ignored. - Window *WebviewWindow - - // Offset indicates the gap in pixels between the system tray and the window - Offset int - - // Debounce is used by Windows to indicate how long to wait before responding to a mouse - // up event on the notification icon. See https://stackoverflow.com/questions/4585283/alternate-showing-hiding-window-when-notify-icon-is-clicked - Debounce time.Duration - // contains filtered or unexported fields -} -``` - - - -## type [WindowEvent](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L76-L79) - -```go -type WindowEvent struct { - Cancelled bool - // contains filtered or unexported fields -} -``` - - - -### func [NewWindowEvent](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L85) - -```go -func NewWindowEvent() *WindowEvent -``` - - - -### func \(\*WindowEvent\) [Cancel](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L89) - -```go -func (w *WindowEvent) Cancel() -``` - - - -### func \(\*WindowEvent\) [Context](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L81) - -```go -func (w *WindowEvent) Context() *WindowEventContext -``` - - - -## type [WindowEventContext](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/context_window_event.go#L10-L13) - -```go -type WindowEventContext struct { - // contains filtered or unexported fields -} -``` - - - -### func \(WindowEventContext\) [DroppedFiles](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/context_window_event.go#L15) - -```go -func (c WindowEventContext) DroppedFiles() []string -``` - - - -## type [WindowEventListener](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/webview_window.go#L93-L95) - -```go -type WindowEventListener struct { - // contains filtered or unexported fields -} -``` - - - -## type [WindowState](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_webview_window.go#L3) - -```go -type WindowState int -``` - - - -```go -const ( - WindowStateNormal WindowState = iota - WindowStateMinimised - WindowStateMaximised - WindowStateFullscreen -) -``` - - - -## type [WindowsOptions](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_application_win.go#L4-L21) - -WindowsOptions contains options for Windows applications. - -```go -type WindowsOptions struct { - - // WndProcInterceptor is a function that will be called for every message sent in the application. - // Use this to hook into the main message loop. This is useful for handling custom window messages. - // If `shouldReturn` is `true` then `returnCode` will be returned by the main message loop. - // If `shouldReturn` is `false` then returnCode will be ignored and the message will be processed by the main message loop. - WndProcInterceptor func(hwnd uintptr, msg uint32, wParam, lParam uintptr) (returnCode uintptr, shouldReturn bool) - - // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. - DisableQuitOnLastWindowClosed bool - - // Path where the WebView2 stores the user data. If empty %APPDATA%\[BinaryName.exe] will be used. - // If the path is not valid, a messagebox will be displayed with the error and the app will exit with error code. - WebviewUserDataPath string - - // Path to the directory with WebView2 executables. If empty WebView2 installed in the system will be used. - WebviewBrowserPath string -} -``` - - - -## type [WindowsWindow](https://github.com/wailsapp/wails/blob/master/v3/pkg/application/options_webview_window_win.go#L15-L77) - -```go -type WindowsWindow struct { - // Select the type of translucent backdrop. Requires Windows 11 22621 or later. - // Only used when window's `BackgroundType` is set to `BackgroundTypeTranslucent`. - // Default: Auto - BackdropType BackdropType - - // Disable the icon in the titlebar - // Default: false - DisableIcon bool - - // Theme (Dark / Light / SystemDefault) - // Default: SystemDefault - The application will follow system theme changes. - Theme Theme - - // Specify custom colours to use for dark/light mode - // Default: nil - CustomTheme *ThemeSettings - - // Disable all window decorations in Frameless mode, which means no "Aero Shadow" and no "Rounded Corner" will be shown. - // "Rounded Corners" are only available on Windows 11. - // Default: false - DisableFramelessWindowDecorations bool - - // WindowMask is used to set the window shape. Use a PNG with an alpha channel to create a custom shape. - // Default: nil - WindowMask []byte - - // WindowMaskDraggable is used to make the window draggable by clicking on the window mask. - // Default: false - WindowMaskDraggable bool - - // WebviewGpuIsDisabled is used to enable / disable GPU acceleration for the webview - // Default: false - WebviewGpuIsDisabled bool - - // ResizeDebounceMS is the amount of time to debounce redraws of webview2 - // when resizing the window - // Default: 0 - ResizeDebounceMS uint16 - - // Disable the menu bar for this window - // Default: false - DisableMenu bool - - // Event mapping for the window. This allows you to define a translation from one event to another. - // Default: nil - EventMapping map[events.WindowEventType]events.WindowEventType - - // HiddenOnTaskbar hides the window from the taskbar - // Default: false - HiddenOnTaskbar bool - - // EnableSwipeGestures enables swipe gestures for the window - // Default: false - EnableSwipeGestures bool - - // EnableFraudulentWebsiteWarnings will enable warnings for fraudulent websites. - // Default: false - EnableFraudulentWebsiteWarnings bool - - // Menu is the menu to use for the window. - Menu *Menu -} -``` diff --git a/mkdocs-website/docs/en/API/window.md b/mkdocs-website/docs/en/API/window.md index aa73ec91a93..727604a5508 100644 --- a/mkdocs-website/docs/en/API/window.md +++ b/mkdocs-website/docs/en/API/window.md @@ -74,7 +74,7 @@ API: `GetScreen() (*Screen, error)` `GetScreen` method returns the screen on which the window is displayed. -#### SetFrameless +### SetFrameless API: `SetFrameless(frameless bool) *WebviewWindow` @@ -82,32 +82,32 @@ This function is used to remove the window frame and title bar. It toggles the framelessness of the window according to the boolean value provided (true for frameless, false for framed). -#### RegisterContextMenu +### RegisterContextMenu API: `RegisterContextMenu(name string, menu *Menu)` This function is used to register a context menu and assigns it the given name. -#### NativeWindowHandle +### NativeWindowHandle API: `NativeWindowHandle() (uintptr, error)` This function is used to fetch the platform native window handle for the window. -#### Focus +### Focus API: `Focus()` This function is used to focus the window. -#### SetEnabled +### SetEnabled API: `SetEnabled(enabled bool)` This function is used to enable/disable the window based on the provided boolean value. -#### SetAbsolutePosition +### SetAbsolutePosition API: `SetAbsolutePosition(x int, y int)` diff --git a/mkdocs-website/docs/en/development/changes.md b/mkdocs-website/docs/en/development/changes.md index ba125147c91..a7d2f85783c 100644 --- a/mkdocs-website/docs/en/development/changes.md +++ b/mkdocs-website/docs/en/development/changes.md @@ -1,455 +1,22 @@ # Changes for v3 !!! note - This is currently an unsorted brain dump of changes. It will be -organised into a more readable format soon. + This is currently an unsorted brain dump of changes. It will be organised into a more readable format soon. + +--8<-- +./docs/en/development/changes_events.md +./docs/en/development/changes_window.md +./docs/en/development/changes_systray.md +./docs/en/development/changes_bindings.md +./docs/en/development/changes_dragndrop.md +./docs/en/development/changes_context_menus.md +./docs/en/development/changes_dialogs.md +./docs/en/development/changes_clipboard.md +./docs/en/development/changes_wml.md +./docs/en/development/changes_plugins.md +./docs/en/development/changes_enums.md +./docs/en/development/changes_logging.md +./docs/en/development/changes_misc.md +--8<-- -## Options -The application options have been revised since v2. - -## Events - -In v3, there are 3 types of events: - -- Application Events -- Window Events -- Custom Events - -### Application Events - -Application events are events that are emitted by the application. These events -include native events such as `ApplicationDidFinishLaunching` on macOS. - -### Window Events - -Window events are events that are emitted by a window. These events include -native events such as `WindowDidBecomeMain` on macOS. Common events are also -defined, so they work cross-platform, e.g. `WindowClosing`. - -### Custom Events - -Events that the user defines are called `WailsEvents`. This is to differentiate -them from the `Event` object that is used to communicate with the browser. -WailsEvents are now objects that encapsulate all the details of an event. This -includes the event name, the data, and the source of the event. - -The data associated with a WailsEvent is now a single value. If multiple values -are required, then a struct can be used. - -### Event callbacks and `Emit` function signature - -The signatures events callbacks (as used by `On`, `Once` & `OnMultiple`) have -changed. In v2, the callback function received optional data. In v3, the -callback function receives a `WailsEvent` object that contains all data related -to the event. - -Similarly, the `Emit` function has changed. Instead of taking a name and -optional data, it now takes a single `WailsEvent` object that it will emit. - -### `Off` and `OffAll` - -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. - -### Hooks - -Event Hooks are a new feature in v3. They allow you to hook into the event -system and perform actions when certain events are emitted. For example, you can -hook into the `WindowClosing` event and perform some cleanup before the window -closes. Hooks can be registered at the application level or at the window level -using `RegisterHook`. Application level are for application events. Window level -hooks will only be called for the window they are registered with. - -### Logging - -Logging in v2 was confusing as both application logs and system (internal) logs -were using the same logger. We have simplified this as follows: - -- Internal logs are now handled using the standard Go `slog` logger. This is - configured using the `logger` option in the application options. By default, - this uses the [tint](https://github.com/lmittmann/tint) logger. -- Application logs can now be achieved through the new `log` plugin which - utilises `slog` under the hood. This plugin provides a simple API for logging - to the console. It is available in both Go and JS. - -### Developer notes - -When emitting an event in Go, it will dispatch the event to local Go listeners -and also each window in the application. When emitting an event in JS, it now -sends the event to the application. This will be processed as if it was emitted -in Go, however the sender ID will be that of the window. - -## Window - -The Window API has largely remained the same, however the methods are now on an -instance of a window rather than the runtime. Some notable differences are: - -- Windows now have a Name that identifies them. This is used to identify the - window when emitting events. -- Windows have even more methods on the that were previously unavailable, such - as `AbsolutePosition` and `ToggleDevTools`. -- Windows can now accept files via native drag and drop. See the Drag and Drop - section for more details. - -## ClipBoard - -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 - -Bindings work in a similar way to v2, by providing a means to bind struct -methods to the frontend. These can be called in the frontend using the binding -wrappers generated by the `wails3 generate bindings` command: - -```javascript -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import { main } from "./models"; - -window.go = window.go || {}; -window.go.main = { - GreetService: { - /** - * GreetService.Greet - * Greet greets a person - * @param name {string} - * @returns {Promise} - **/ - Greet: function (name) { - wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); - }, - - /** - * GreetService.GreetPerson - * GreetPerson greets a person - * @param person {main.Person} - * @returns {Promise} - **/ - GreetPerson: function (person) { - wails.CallByID(4021313248, ...Array.prototype.slice.call(arguments, 0)); - }, - }, -}; -``` - -Bound methods are obfuscated by default, and are identified using uint32 IDs, -calculated using the -[FNV hashing algorithm](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function). -This is to prevent the method name from being exposed in production builds. In -debug mode, the method IDs are logged along with the calculated ID of the method -to aid in debugging. If you wish to add an extra layer of obfuscation, you can -use the `BindAliases` option. This allows you to specify a map of alias IDs to -method IDs. When the frontend calls a method using an ID, the method ID will be -looked up in the alias map first for a match. If it does not find it, it assumes -it's a standard method ID and tries to find the method in the usual way. - -Example: - -```go - app := application.New(application.Options{ - Bind: []any{ - &GreetService{}, - }, - BindAliases: map[uint32]uint32{ - 1: 1411160069, - 2: 4021313248, - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) -``` - -We can now call using this alias in the frontend: `wails.Call(1, "world!")`. - -### Insecure calls - -If you don't mind your calls being available in plain text in your binary and -have no intention of using [garble](https://github.com/burrowers/garble), then -you can use the insecure `wails.CallByName()` method. This method takes the -fully qualified name of the method to call and the arguments to pass to it. -Example: - - ```go - wails.CallByName("main.GreetService.Greet", "world!") - ``` - -!!! danger - - This is only provided as a convenience method for development. It is not recommended to use this in production. - -## Dialogs - -Dialogs are now available in JavaScript! - -### Windows - -Dialog buttons in Windows are not configurable and are constant depending on the -type of dialog. To trigger a callback when a button is pressed, create a button -with the same name as the button you wish to have the callback attached to. -Example: Create a button with the label `Ok` and use `OnClick()` to set the -callback method: - -```go - dialog := app.QuestionDialog(). - SetTitle("Update"). - SetMessage("The cancel button is selected when pressing escape") - ok := dialog.AddButton("Ok") - ok.OnClick(func() { - // Do something - }) - no := dialog.AddButton("Cancel") - dialog.SetDefaultButton(ok) - dialog.SetCancelButton(no) - dialog.Show() -``` - -## Drag and Drop - -Native drag and drop can be enabled per-window. Simply set the -`EnableDragAndDrop` window config option to `true` and the window will allow -files to be dragged onto it. When this happens, the `events.FilesDropped` event -will be emitted. The filenames can then be retrieved from the -`WindowEvent.Context()` using the `DroppedFiles()` method. This returns a slice -of strings containing the filenames. - -## Context Menus - -Context menus are contextual menus that are shown when the user right-clicks on -an element. Creating a context menu is the same as creating a standard menu , by -using `app.NewMenu()`. To make the context menu available to a window, call -`window.RegisterContextMenu(name, menu)`. The name will be the id of the context -menu and used by the frontend. - -To indicate that an element has a context menu, add the `data-contextmenu` -attribute to the element. The value of this attribute should be the name of a -context menu previously registered with the window. - -It is possible to register a context menu at the application level, making it -available to all windows. This can be done using -`app.RegisterContextMenu(name, menu)`. If a context menu cannot be found at the -window level, the application context menus will be checked. A demo of this can -be found in `v3/examples/contextmenus`. - -## Wails Markup Language (WML) - -The Wails Markup Language is a simple markup language that allows you to add -functionality to standard HTML elements without the use of Javascript. - -The following tags are currently supported: - -### `data-wml-event` - -This specifies that a Wails event will be emitted when the element is clicked. -The value of the attribute should be the name of the event to emit. - -Example: - -```html - -``` - -Sometimes you need the user to confirm an action. This can be done by adding the -`data-wml-confirm` attribute to the element. The value of this attribute will be -the message to display to the user. - -Example: - -```html - -``` - -### `data-wml-window` - -Any `wails.window` method can be called by adding the `data-wml-window` -attribute to an element. The value of the attribute should be the name of the -method to call. The method name should be in the same case as the method. - -```html - -``` - -### `data-wml-trigger` - -This attribute specifies which javascript event should trigger the action. The -default is `click`. - -```html - -``` - -## Systray - -Wails 3 comes with a built-in systray. This is a fully featured systray that has -been designed to be as simple as possible to use. It is possible to set the -icon, tooltip and menu of the systray. It is possible to also "attach" a window -to the systray. Doing this will provide the following functionality: - -- Clicking the systray icon with toggle the window visibility -- Right-clicking the systray will open the menu, if there is one - -On macOS, if there is no attached window, the systray will use the default -method of displaying the menu (any button). If there is an attached window but -no menu, the systray will toggle the window regardless of the button pressed. - -## Plugins - -Plugins are a way to extend the functionality of your Wails application. - -### Creating a plugin - -Plugins are standard Go structure that adhere to the following interface: - -```go -type Plugin interface { - Name() string - Init(*application.App) error - Shutdown() - CallableByJS() []string - InjectJS() string -} -``` - -The `Name()` method returns the name of the plugin. This is used for logging -purposes. - -The `Init(*application.App) error` method is called when the plugin is loaded. -The `*application.App` parameter is the application that the plugin is being -loaded into. Any errors will prevent the application from starting. - -The `Shutdown()` method is called when the application is shutting down. - -The `CallableByJS()` method returns a list of exported functions that can be -called from the frontend. These method names must exactly match the names of the -methods exported by the plugin. - -The `InjectJS()` method returns JavaScript that should be injected into all -windows as they are created. This is useful for adding custom JavaScript -functions that complement the plugin. - -### Tips - -#### Enums - -In Go, enums are often defined as a type and a set of constants. For example: - -```go -type MyEnum int - -const ( - MyEnumOne MyEnum = iota - MyEnumTwo - MyEnumThree -) -``` - -Due to incompatibility between Go and JavaScript, custom types cannot be used in -this way. The best strategy is to use a type alias for float64: - -```go -type MyEnum = float64 - -const ( - MyEnumOne MyEnum = iota - MyEnumTwo - MyEnumThree -) -``` - -In Javascript, you can then use the following: - -```js -const MyEnum = { - MyEnumOne: 0, - MyEnumTwo: 1, - MyEnumThree: 2, -}; -``` - -- Why use `float64`? Can't we use `int`? - - Because JavaScript doesn't have a concept of `int`. Everything is a - `number`, which translates to `float64` in Go. There are also restrictions - on casting types in Go's reflection package, which means using `int` doesn't - work. - -### BackgroundColour - -In v2, this was a pointer to an `RGBA` struct. In v3, this is an `RGBA` struct -value. - -### WindowIsTranslucent - -This flag has been removed. Now there is a `BackgroundType` flag that can be -used to set the type of background the window should have. This flag can be set -to any of the following values: - -- `BackgroundTypeSolid` - The window will have a solid background -- `BackgroundTypeTransparent` - The window will have a transparent background -- `BackgroundTypeTranslucent` - The window will have a translucent background - -On Windows, if the `BackgroundType` is set to `BackgroundTypeTranslucent`, the -type of translucency can be set using the `BackdropType` flag in the -`WindowsWindow` options. This can be set to any of the following values: - -- `Auto` - The window will use an effect determined by the system -- `None` - The window will have no background -- `Mica` - The window will use the Mica effect -- `Acrylic` - The window will use the acrylic effect -- `Tabbed` - The window will use the tabbed effect - -## Windows Application Options - -### WndProcInterceptor - -If this is set, the WndProc will be intercepted and the function will be called. -This allows you to handle Windows messages directly. The function should have -the following signature: - -```go -func(hwnd uintptr, msg uint32, wParam, lParam uintptr) (returnValue uintptr, shouldReturn) -``` - -The `shouldReturn` value should be set to `true` if the returnValue should be -returned by the main wndProc method. If it is set to `false`, the return value -will be ignored and the message will continue to be processed by the main -wndProc method. - -## Hide Window on Close + OnBeforeClose - -In v2, there was the `HideWindowOnClose` flag to hide the window when it closed. -There was a logical overlap between this flag and the `OnBeforeClose` callback. -In v3, the `HideWindowOnClose` flag has been removed and the `OnBeforeClose` -callback has been renamed to `ShouldClose`. The `ShouldClose` callback is called -when the user attempts to close a window. If the callback returns `true`, the -window will close. If it returns `false`, the window will not close. This can be -used to hide the window instead of closing it. - -## Window Drag - -In v2, the `--wails-drag` attribute was used to indicate that an element could -be used to drag the window. In v3, this has been replaced with -`--webkit-app-region` to be more in line with the way other frameworks handle -this. The `--webkit-app-region` attribute can be set to any of the following -values: - -- `drag` - The element can be used to drag the window -- `no-drag` - The element cannot be used to drag the window - -We would have ideally liked to use `app-region`, however this is not supported -by the `getComputedStyle` call on webkit on macOS. diff --git a/mkdocs-website/docs/en/development/changes_bindings.md b/mkdocs-website/docs/en/development/changes_bindings.md new file mode 100644 index 00000000000..92846f29f82 --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_bindings.md @@ -0,0 +1,87 @@ +## Bindings + +Bindings work in a similar way to v2, by providing a means to bind struct +methods to the frontend. These can be called in the frontend using the binding +wrappers generated by the `wails3 generate bindings` command: + +```javascript +// @ts-check +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +import { main } from "./models"; + +window.go = window.go || {}; +window.go.main = { + GreetService: { + /** + * GreetService.Greet + * Greet greets a person + * @param name {string} + * @returns {Promise} + **/ + Greet: function (name) { + wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); + }, + + /** + * GreetService.GreetPerson + * GreetPerson greets a person + * @param person {main.Person} + * @returns {Promise} + **/ + GreetPerson: function (person) { + wails.CallByID(4021313248, ...Array.prototype.slice.call(arguments, 0)); + }, + }, +}; +``` + +Bound methods are obfuscated by default, and are identified using uint32 IDs, +calculated using the +[FNV hashing algorithm](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function). +This is to prevent the method name from being exposed in production builds. In +debug mode, the method IDs are logged along with the calculated ID of the method +to aid in debugging. If you wish to add an extra layer of obfuscation, you can +use the `BindAliases` option. This allows you to specify a map of alias IDs to +method IDs. When the frontend calls a method using an ID, the method ID will be +looked up in the alias map first for a match. If it does not find it, it assumes +it's a standard method ID and tries to find the method in the usual way. + +Example: + +```go + app := application.New(application.Options{ + Bind: []any{ + &GreetService{}, + }, + BindAliases: map[uint32]uint32{ + 1: 1411160069, + 2: 4021313248, + }, + Assets: application.AssetOptions{ + Handler: application.AssetFileServerFS(assets), + }, + Mac: application.MacOptions{ + ApplicationShouldTerminateAfterLastWindowClosed: true, + }, + }) +``` + +We can now call using this alias in the frontend: `wails.Call(1, "world!")`. + +### Insecure calls + +If you don't mind your calls being available in plain text in your binary and +have no intention of using [garble](https://github.com/burrowers/garble), then +you can use the insecure `wails.CallByName()` method. This method takes the +fully qualified name of the method to call and the arguments to pass to it. +Example: + + ```go + wails.CallByName("main.GreetService.Greet", "world!") + ``` + +!!! danger + + This is only provided as a convenience method for development. It is not recommended to use this in production. diff --git a/mkdocs-website/docs/en/development/changes_clipboard.md b/mkdocs-website/docs/en/development/changes_clipboard.md new file mode 100644 index 00000000000..bc17d8cbd50 --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_clipboard.md @@ -0,0 +1,6 @@ +## ClipBoard + +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. \ No newline at end of file diff --git a/mkdocs-website/docs/en/development/changes_context_menus.md b/mkdocs-website/docs/en/development/changes_context_menus.md new file mode 100644 index 00000000000..b8a333b50d1 --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_context_menus.md @@ -0,0 +1,17 @@ +## Context Menus + +Context menus are contextual menus that are shown when the user right-clicks on +an element. Creating a context menu is the same as creating a standard menu , by +using `app.NewMenu()`. To make the context menu available to a window, call +`window.RegisterContextMenu(name, menu)`. The name will be the id of the context +menu and used by the frontend. + +To indicate that an element has a context menu, add the `data-contextmenu` +attribute to the element. The value of this attribute should be the name of a +context menu previously registered with the window. + +It is possible to register a context menu at the application level, making it +available to all windows. This can be done using +`app.RegisterContextMenu(name, menu)`. If a context menu cannot be found at the +window level, the application context menus will be checked. A demo of this can +be found in `v3/examples/contextmenus`. \ No newline at end of file diff --git a/mkdocs-website/docs/en/development/changes_dialogs.md b/mkdocs-website/docs/en/development/changes_dialogs.md new file mode 100644 index 00000000000..f0b68a13590 --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_dialogs.md @@ -0,0 +1,25 @@ +## Dialogs + +Dialogs are now available in JavaScript! + +### Windows + +Dialog buttons in Windows are not configurable and are constant depending on the +type of dialog. To trigger a callback when a button is pressed, create a button +with the same name as the button you wish to have the callback attached to. +Example: Create a button with the label `Ok` and use `OnClick()` to set the +callback method: + +```go + dialog := app.QuestionDialog(). + SetTitle("Update"). + SetMessage("The cancel button is selected when pressing escape") + ok := dialog.AddButton("Ok") + ok.OnClick(func() { + // Do something + }) + no := dialog.AddButton("Cancel") + dialog.SetDefaultButton(ok) + dialog.SetCancelButton(no) + dialog.Show() +``` \ No newline at end of file diff --git a/mkdocs-website/docs/en/development/changes_dragndrop.md b/mkdocs-website/docs/en/development/changes_dragndrop.md new file mode 100644 index 00000000000..5a6fbc95f4e --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_dragndrop.md @@ -0,0 +1,8 @@ +## Drag and Drop + +Native drag and drop can be enabled per-window. Simply set the +`EnableDragAndDrop` window config option to `true` and the window will allow +files to be dragged onto it. When this happens, the `events.FilesDropped` event +will be emitted. The filenames can then be retrieved from the +`WindowEvent.Context()` using the `DroppedFiles()` method. This returns a slice +of strings containing the filenames. diff --git a/mkdocs-website/docs/en/development/changes_enums.md b/mkdocs-website/docs/en/development/changes_enums.md new file mode 100644 index 00000000000..570a15a9d7d --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_enums.md @@ -0,0 +1,42 @@ +#### Enums + +In Go, enums are often defined as a type and a set of constants. For example: + +```go +type MyEnum int + +const ( + MyEnumOne MyEnum = iota + MyEnumTwo + MyEnumThree +) +``` + +Due to incompatibility between Go and JavaScript, custom types cannot be used in +this way. The best strategy is to use a type alias for float64: + +```go +type MyEnum = float64 + +const ( + MyEnumOne MyEnum = iota + MyEnumTwo + MyEnumThree +) +``` + +In Javascript, you can then use the following: + +```js +const MyEnum = { + MyEnumOne: 0, + MyEnumTwo: 1, + MyEnumThree: 2, +}; +``` + +- Why use `float64`? Can't we use `int`? + - Because JavaScript doesn't have a concept of `int`. Everything is a + `number`, which translates to `float64` in Go. There are also restrictions + on casting types in Go's reflection package, which means using `int` doesn't + work. \ No newline at end of file diff --git a/mkdocs-website/docs/en/development/changes_events.md b/mkdocs-website/docs/en/development/changes_events.md new file mode 100644 index 00000000000..4ca0c0ee2e7 --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_events.md @@ -0,0 +1,62 @@ +## Events + +In v3, there are 3 types of events: + +- Application Events +- Window Events +- Custom Events + +### Application Events + +Application events are events that are emitted by the application. These events +include native events such as `ApplicationDidFinishLaunching` on macOS. + +### Window Events + +Window events are events that are emitted by a window. These events include +native events such as `WindowDidBecomeMain` on macOS. Common events are also +defined, so they work cross-platform, e.g. `WindowClosing`. + +### Custom Events + +Events that the user defines are called `WailsEvents`. This is to differentiate +them from the `Event` object that is used to communicate with the browser. +WailsEvents are now objects that encapsulate all the details of an event. This +includes the event name, the data, and the source of the event. + +The data associated with a WailsEvent is now a single value. If multiple values +are required, then a struct can be used. + +### Event callbacks and `Emit` function signature + +The signatures events callbacks (as used by `On`, `Once` & `OnMultiple`) have +changed. In v2, the callback function received optional data. In v3, the +callback function receives a `WailsEvent` object that contains all data related +to the event. + +Similarly, the `Emit` function has changed. Instead of taking a name and +optional data, it now takes a single `WailsEvent` object that it will emit. + +### `Off` and `OffAll` + +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. + +### Hooks + +Event Hooks are a new feature in v3. They allow you to hook into the event +system and perform actions when certain events are emitted. For example, you can +hook into the `WindowClosing` event and perform some cleanup before the window +closes. Hooks can be registered at the application level or at the window level +using `RegisterHook`. Application level are for application events. Window level +hooks will only be called for the window they are registered with. + +### Developer notes + +When emitting an event in Go, it will dispatch the event to local Go listeners +and also each window in the application. When emitting an event in JS, it now +sends the event to the application. This will be processed as if it was emitted +in Go, however the sender ID will be that of the window. diff --git a/mkdocs-website/docs/en/development/changes_logging.md b/mkdocs-website/docs/en/development/changes_logging.md new file mode 100644 index 00000000000..04ce08055ad --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_logging.md @@ -0,0 +1,11 @@ +### Logging + +Logging in v2 was confusing as both application logs and system (internal) logs +were using the same logger. We have simplified this as follows: + +- Internal logs are now handled using the standard Go `slog` logger. This is + configured using the `logger` option in the application options. By default, + this uses the [tint](https://github.com/lmittmann/tint) logger. +- Application logs can now be achieved through the new `log` plugin which + utilises `slog` under the hood. This plugin provides a simple API for logging + to the console. It is available in both Go and JS. diff --git a/mkdocs-website/docs/en/development/changes_misc.md b/mkdocs-website/docs/en/development/changes_misc.md new file mode 100644 index 00000000000..fda52cf50fb --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_misc.md @@ -0,0 +1,42 @@ +### Misc + +## Windows Application Options + +### WndProcInterceptor + +If this is set, the WndProc will be intercepted and the function will be called. +This allows you to handle Windows messages directly. The function should have +the following signature: + +```go +func(hwnd uintptr, msg uint32, wParam, lParam uintptr) (returnValue uintptr, shouldReturn) +``` + +The `shouldReturn` value should be set to `true` if the returnValue should be +returned by the main wndProc method. If it is set to `false`, the return value +will be ignored and the message will continue to be processed by the main +wndProc method. + +## Hide Window on Close + OnBeforeClose + +In v2, there was the `HideWindowOnClose` flag to hide the window when it closed. +There was a logical overlap between this flag and the `OnBeforeClose` callback. +In v3, the `HideWindowOnClose` flag has been removed and the `OnBeforeClose` +callback has been renamed to `ShouldClose`. The `ShouldClose` callback is called +when the user attempts to close a window. If the callback returns `true`, the +window will close. If it returns `false`, the window will not close. This can be +used to hide the window instead of closing it. + +## Window Drag + +In v2, the `--wails-drag` attribute was used to indicate that an element could +be used to drag the window. In v3, this has been replaced with +`--webkit-app-region` to be more in line with the way other frameworks handle +this. The `--webkit-app-region` attribute can be set to any of the following +values: + +- `drag` - The element can be used to drag the window +- `no-drag` - The element cannot be used to drag the window + +We would have ideally liked to use `app-region`, however this is not supported +by the `getComputedStyle` call on webkit on macOS. diff --git a/mkdocs-website/docs/en/development/changes_plugins.md b/mkdocs-website/docs/en/development/changes_plugins.md new file mode 100644 index 00000000000..b32c18abe50 --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_plugins.md @@ -0,0 +1,34 @@ +## Plugins + +Plugins are a way to extend the functionality of your Wails application. + +### Creating a plugin + +Plugins are standard Go structure that adhere to the following interface: + +```go +type Plugin interface { + Name() string + Init(*application.App) error + Shutdown() + CallableByJS() []string + InjectJS() string +} +``` + +The `Name()` method returns the name of the plugin. This is used for logging +purposes. + +The `Init(*application.App) error` method is called when the plugin is loaded. +The `*application.App` parameter is the application that the plugin is being +loaded into. Any errors will prevent the application from starting. + +The `Shutdown()` method is called when the application is shutting down. + +The `CallableByJS()` method returns a list of exported functions that can be +called from the frontend. These method names must exactly match the names of the +methods exported by the plugin. + +The `InjectJS()` method returns JavaScript that should be injected into all +windows as they are created. This is useful for adding custom JavaScript +functions that complement the plugin. diff --git a/mkdocs-website/docs/en/development/changes_systray.md b/mkdocs-website/docs/en/development/changes_systray.md new file mode 100644 index 00000000000..32a51837c65 --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_systray.md @@ -0,0 +1,13 @@ +## Systray + +Wails 3 comes with a built-in systray. This is a fully featured systray that has +been designed to be as simple as possible to use. It is possible to set the +icon, tooltip and menu of the systray. It is possible to also "attach" a window +to the systray. Doing this will provide the following functionality: + +- Clicking the systray icon with toggle the window visibility +- Right-clicking the systray will open the menu, if there is one + +On macOS, if there is no attached window, the systray will use the default +method of displaying the menu (any button). If there is an attached window but +no menu, the systray will toggle the window regardless of the button pressed. \ No newline at end of file diff --git a/mkdocs-website/docs/en/development/changes_window.md b/mkdocs-website/docs/en/development/changes_window.md new file mode 100644 index 00000000000..f87962a82e9 --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_window.md @@ -0,0 +1,36 @@ +## Window + +The Window API has largely remained the same, however the methods are now on an +instance of a window rather than the runtime. Some notable differences are: + +- Windows now have a Name that identifies them. This is used to identify the + window when emitting events. +- Windows have even more methods on the that were previously unavailable, such + as `AbsolutePosition` and `ToggleDevTools`. +- Windows can now accept files via native drag and drop. See the Drag and Drop + section for more details. + +### BackgroundColour + +In v2, this was a pointer to an `RGBA` struct. In v3, this is an `RGBA` struct +value. + +### WindowIsTranslucent + +This flag has been removed. Now there is a `BackgroundType` flag that can be +used to set the type of background the window should have. This flag can be set +to any of the following values: + +- `BackgroundTypeSolid` - The window will have a solid background +- `BackgroundTypeTransparent` - The window will have a transparent background +- `BackgroundTypeTranslucent` - The window will have a translucent background + +On Windows, if the `BackgroundType` is set to `BackgroundTypeTranslucent`, the +type of translucency can be set using the `BackdropType` flag in the +`WindowsWindow` options. This can be set to any of the following values: + +- `Auto` - The window will use an effect determined by the system +- `None` - The window will have no background +- `Mica` - The window will use the Mica effect +- `Acrylic` - The window will use the acrylic effect +- `Tabbed` - The window will use the tabbed effect \ No newline at end of file diff --git a/mkdocs-website/docs/en/development/changes_wml.md b/mkdocs-website/docs/en/development/changes_wml.md new file mode 100644 index 00000000000..c06a214f360 --- /dev/null +++ b/mkdocs-website/docs/en/development/changes_wml.md @@ -0,0 +1,50 @@ +## Wails Markup Language (WML) + +The Wails Markup Language is a simple markup language that allows you to add +functionality to standard HTML elements without the use of Javascript. + +The following tags are currently supported: + +### `data-wml-event` + +This specifies that a Wails event will be emitted when the element is clicked. +The value of the attribute should be the name of the event to emit. + +Example: + +```html + +``` + +Sometimes you need the user to confirm an action. This can be done by adding the +`data-wml-confirm` attribute to the element. The value of this attribute will be +the message to display to the user. + +Example: + +```html + +``` + +### `data-wml-window` + +Any `wails.window` method can be called by adding the `data-wml-window` +attribute to an element. The value of the attribute should be the name of the +method to call. The method name should be in the same case as the method. + +```html + +``` + +### `data-wml-trigger` + +This attribute specifies which javascript event should trigger the action. The +default is `click`. + +```html + +``` diff --git a/mkdocs-website/docs/zh/API/application.md b/mkdocs-website/docs/zh/API/application.md deleted file mode 100644 index 76f03663598..00000000000 --- a/mkdocs-website/docs/zh/API/application.md +++ /dev/null @@ -1,335 +0,0 @@ -# 应用程序 - -应用程序 API 用于使用 Wails 框架创建应用程序。 - -### New - -API:`New(appOptions Options) *App` - -`New(appOptions Options)` 使用给定的应用程序选项创建一个新的应用程序。它对未指定 -的选项应用默认值,将其与提供的选项合并,然后初始化并返回应用程序的实例。 - -如果在初始化过程中出现错误,应用程序将停止,并显示提供的错误消息。 - -需要注意的是,如果全局应用程序实例已经存在,将返回该实例,而不是创建新的实例。 - -```go title="main.go" hl_lines="6-9" -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -func main() { - app := application.New(application.Options{ - Name: "WebviewWindow Demo", - // 其他选项 - }) - - // 其余的应用程序逻辑 -} -``` - -### Get - -`Get()` 返回全局应用程序实例。在代码的不同部分需要访问应用程序时非常有用。 - -```go - // 获取应用程序实例 - app := application.Get() -``` - -### Capabilities - -API:`Capabilities() capabilities.Capabilities` - -`Capabilities()` 返回应用程序当前具有的功能的映射。这些功能可以是操作系统提供的 -不同功能,如 webview 功能。 - -```go - // 获取应用程序的功能 - capabilities := app.Capabilities() - if capabilities.HasNativeDrag { - // 做一些事情 - } -``` - -### GetPID - -API:`GetPID() int` - -`GetPID()` 返回应用程序的进程 ID。 - -```go - pid := app.GetPID() -``` - -### Run - -API:`Run() error` - -`Run()` 启动应用程序及其组件的执行。 - -```go - app := application.New(application.Options{ - // 选项 - }) - // 运行应用程序 - err := application.Run() - if err != nil { - // 处理错误 - } -``` - -### Quit - -API:`Quit()` - -`Quit()` 通过销毁窗口和可能的其他组件退出应用程序。 - -```go - // 退出应用程序 - app.Quit() -``` - -### IsDarkMode - -API:`IsDarkMode() bool` - -`IsDarkMode()` 检查应用程序是否在暗模式下运行。它返回一个布尔值,指示是否启用了 -暗模式。 - -```go - // 检查是否启用了暗模式 - if app.IsDarkMode() { - // 做一些事情 - } -``` - -### Hide - -API:`Hide()` - -`Hide()` 隐藏应用程序窗口。 - -```go - // 隐藏应用程序窗口 - app.Hide() -``` - -### Show - -API:`Show()` - -`Show()` 显示应用程序窗口。 - -```go - // 显示应用程序窗口 - app.Show() -``` - -### NewWebviewWindow - -API:`NewWebviewWindow() *WebviewWindow` - -`NewWebviewWindow()` 使用默认选项创建一个新的 Webview 窗口,并返回它。 - -```go - // 创建一个新的 Webview 窗口 - window := app.NewWebviewWindow() -``` - -### NewWebviewWindowWithOptions - -API:`NewWebviewWindowWithOptions(windowOptions WebviewWindowOptions) *WebviewWindow` - -`NewWebviewWindowWithOptions()` 使用自定义选项创建一个新的 Webview 窗口。新创建 -的窗口将添加到应用程序管理的窗口映射中。 - -```go - // 使用自定义选项创建一个新的 Webview 窗口 - window := app.NewWebviewWindowWithOptions(WebviewWindowOptions{ - Name: "Main", - Title: "My Window", - Width: 800, - Height: 600, - }) -``` - -### OnWindowCreation - -API:`OnWindowCreation(callback func(window *WebviewWindow))` - -`OnWindowCreation()` 注册一个回调函数,当创建窗口时调用该函数。 - -```go - // 注册一个回调函数,当创建窗口时调用该函数 - app.OnWindowCreation(func(window *WebviewWindow) { - // 做一些事情 - }) -``` - -### GetWindowByName - -API:`GetWindowByName(name string) *WebviewWindow` - -`GetWindowByName()` 获取并返回具有特定名称的窗口。 - -```go - // 通过名称获取窗口 - window := app.GetWindowByName("Main") -``` - -### CurrentWindow - -API:`CurrentWindow() *WebviewWindow` - -`CurrentWindow()` 获取并返回应用程序中当前活动窗口的指针。如果没有窗口,则返回 -nil。 - -```go - // 获取当前窗口 - window := app.CurrentWindow() -``` - -### RegisterContextMenu - -API:`RegisterContextMenu(name string, menu *Menu)` - -`RegisterContextMenu()` 注册具有给定名称的上下文菜单。稍后可以在应用程序中使用该 -菜单。 - -```go - - // 创建一个新的菜单 - ctxmenu := app.NewMenu() - - // 将菜单注册为上下文菜单 - app.RegisterContextMenu("MyContextMenu", ctxmenu) -``` - -### SetMenu - -API:`SetMenu(menu *Menu)` - -`SetMenu()` 设置应用程序的菜单。在 Mac 上,这将是全局菜单。对于 Windows 和 -Linux,这将是任何新窗口的默认菜单。 - -```go - // 创建一个新的菜单 - menu := app.NewMenu() - - // 设置应用程序的菜单 - app.SetMenu(menu) -``` - -### ShowAboutDialog - -API:`ShowAboutDialog()` - -`ShowAboutDialog()` 显示一个 "关于" 对话框。可以显示应用程序的名称、描述和图标。 - -```go - // 显示关于对话框 - app.ShowAboutDialog() -``` - -### Info - -API:`InfoDialog()` - -`InfoDialog()` 创建并返回一个具有 `InfoDialogType` 的 `MessageDialog` 的新实例。 -此对话框通常用于向用户显示信息消息。 - -### Question - -API:`QuestionDialog()` - -`QuestionDialog()` 创建并返回一个具有 `QuestionDialogType` 的 `MessageDialog` 的 -新实例。此对话框通常用于向用户提问并期望回应。 - -### Warning - -API:`WarningDialog()` - -`WarningDialog()` 创建并返回一个具有 `WarningDialogType` 的 `MessageDialog` 的新 -实例。如其名称所示,此对话框主要用于向用户显示警告消息。 - -### Error - -API:`ErrorDialog()` - -`ErrorDialog()` 创建并返回一个具有 `ErrorDialogType` 的 `MessageDialog` 的新实 -例。此对话框设计用于在需要向用户显示错误消息时使用。 - -### OpenFile - -API:`OpenFileDialog()` - -`OpenFileDialog()` 创建并返回一个新的 `OpenFileDialogStruct`。此对话框提示用户从 -其文件系统中选择一个或多个文件。 - -### SaveFile - -API:`SaveFileDialog()` - -`SaveFileDialog()` 创建并返回一个新的 `SaveFileDialogStruct`。此对话框提示用户选 -择其文件系统上的位置以保存文件。 - -### OpenDirectory - -API:`OpenDirectoryDialog()` - -`OpenDirectoryDialog()` 创建并返回一个具有 `OpenDirectoryDialogType` 的 -`MessageDialog` 的新实例。此对话框使用户能够从其文件系统中选择目录。 - -### On - -API:`On(eventType events.ApplicationEventType, callback func(event *Event)) func()` - -`On()` 注册特定应用程序事件的事件侦听器。提供的回调函数将在相应事件发生时触发。 -该函数返回一个可调用的函数,用于删除侦听器。 - -### RegisterHook - -API:`RegisterHook(eventType events.ApplicationEventType, callback func(event *Event)) func()` - -`RegisterHook()` 注册要在特定事件期间作为钩子运行的回调函数。这些钩子在使用 -`On()` 附加的侦听器之前运行。该函数返回一个可调用的函数,用于删除钩子。 - -### GetPrimaryScreen - -API:`GetPrimaryScreen() (*Screen, error)` - -`GetPrimaryScreen()` 返回系统的主屏幕。 - -### GetScreens - -API:`GetScreens() ([]*Screen, error)` - -`GetScreens()` 返回有关连接到系统的所有屏幕的信息。 - -这是提供的 `App` 结构中导出的方法的简要摘要。请注意,有关更详细的功能或注意事 -项,请参考实际的 Go 代码或进一步的内部文档。 - -## Options - -```go title="application_options.go" ---8<-- -../v3/pkg/application/options_application.go ---8<-- -``` - -### Windows 选项 - -```go title="application_options_windows.go" ---8<-- -../v3/pkg/application/options_application_win.go ---8<-- -``` - -### Mac 选项 - -```go title="options_application_mac.go" ---8<-- -../v3/pkg/application/options_application_mac.go ---8<-- -``` diff --git a/mkdocs-website/docs/zh/API/mainthread.md b/mkdocs-website/docs/zh/API/mainthread.md deleted file mode 100644 index 0ddb768e6ae..00000000000 --- a/mkdocs-website/docs/zh/API/mainthread.md +++ /dev/null @@ -1,45 +0,0 @@ -# 主线程函数 - -这些方法是在主线程上运行代码的实用函数。当您想要在UI线程上运行自定义代码时,这是 -必需的。 - -### InvokeSync - -API: `InvokeSync(fn func())` - -此函数以同步方式运行传入的函数(`fn`)。它使用一个`WaitGroup`(`wg`)确保主线程 -在`fn`函数完成之前等待,然后才继续执行。如果在`fn`内部发生恐慌,它将传递给应用程 -序选项中定义的处理程序函数`PanicHandler`。 - -### InvokeSyncWithResult - -API: `InvokeSyncWithResult[T any](fn func() T) (res T)` - -此函数与`InvokeSync(fn func())`类似,但它返回一个结果。可用于调用具有单个返回值 -的任何函数。 - -### InvokeSyncWithError - -API: `InvokeSyncWithError(fn func() error) (err error)` - -此函数同步运行`fn`并返回`fn`产生的任何错误。请注意,如果在`fn`执行期间发生恐慌, -此函数将从恢复。 - -### InvokeSyncWithResultAndError - -API: -`InvokeSyncWithResultAndError[T any](fn func() (T, error)) (res T, err error)` - -此函数同步运行`fn`并返回类型为`T`的结果和一个错误。 - -### InvokeAsync - -API: `InvokeAsync(fn func())` - -此函数以异步方式运行`fn`。它在主线程上运行给定的函数。如果在`fn`内部发生恐慌,它 -将传递给应用程序选项中定义的处理程序函数`PanicHandler`。 - ---- - -注意:这些函数将阻塞执行,直到`fn`完成。确保`fn`不会阻塞至关重要。如果需要运行阻 -塞函数,请改用`InvokeAsync`。 diff --git a/mkdocs-website/docs/zh/API/menu.md b/mkdocs-website/docs/zh/API/menu.md deleted file mode 100644 index aefa5801c29..00000000000 --- a/mkdocs-website/docs/zh/API/menu.md +++ /dev/null @@ -1,66 +0,0 @@ -# 菜单 - -可以创建菜单并添加到应用程序中。它们可以用于创建上下文菜单、系统托盘菜单和应用程 -序菜单。 - -要创建一个新菜单,请调用: - -```go - // 创建一个新菜单 - menu := app.NewMenu() -``` - -然后,`Menu` 类型上可用以下操作: - -### 添加 - -API:`Add(label string) *MenuItem` - -此方法以 `string` 类型的 `label` 作为输入,并将具有给定标签的新 `MenuItem` 添加 -到菜单中。它返回添加的 `MenuItem`。 - -### 添加分隔符 - -API:`AddSeparator()` - -此方法将一个新的分隔符 `MenuItem` 添加到菜单中。 - -### 添加复选框 - -API:`AddCheckbox(label string, enabled bool) *MenuItem` - -此方法以 `string` 类型的 `label` 和 `bool` 类型的 `enabled` 作为输入,并将具有给 -定标签和启用状态的新复选框 `MenuItem` 添加到菜单中。它返回添加的 `MenuItem`。 - -### 添加单选按钮 - -API:`AddRadio(label string, enabled bool) *MenuItem` - -此方法以 `string` 类型的 `label` 和 `bool` 类型的 `enabled` 作为输入,并将具有给 -定标签和启用状态的新单选按钮 `MenuItem` 添加到菜单中。它返回添加的 `MenuItem`。 - -### 更新 - -API:`Update()` - -此方法处理任何单选按钮组,并在菜单未初始化时更新菜单。 - -### 添加子菜单 - -API:`AddSubmenu(s string) *Menu` - -此方法以 `string` 类型的 `s` 作为输入,并将具有给定标签的新子菜单 `MenuItem` 添 -加到菜单中。它返回添加的子菜单。 - -### 添加角色 - -API:`AddRole(role Role) *Menu` - -此方法以 `Role` 类型的 `role` 作为输入,如果不为 `nil`,则将其添加到菜单中,并返 -回 `Menu`。 - -### 设置标签 - -API:`SetLabel(label string)` - -此方法设置 `Menu` 的 `label`。 diff --git a/mkdocs-website/docs/zh/API/systray.md b/mkdocs-website/docs/zh/API/systray.md deleted file mode 100644 index fde922e24a0..00000000000 --- a/mkdocs-website/docs/zh/API/systray.md +++ /dev/null @@ -1,103 +0,0 @@ -# 系统托盘 - -系统托盘位于桌面环境的通知区域,可以包含当前运行应用程序的图标和特定系统通知。 - -您可以通过调用 `app.NewSystemTray()` 来创建一个系统托盘: - -```go - // 创建一个新的系统托盘 -tray := app.NewSystemTray() -``` - -`SystemTray` 类型上提供了以下方法: - -### SetLabel - -API:`SetLabel(label string)` - -`SetLabel` 方法设置托盘的标签。 - -### Label - -API:`Label() string` - -`Label` 方法获取托盘的标签。 - -### PositionWindow - -API:`PositionWindow(*WebviewWindow, offset int) error` - -`PositionWindow` 方法调用了 `AttachWindow` 和 `WindowOffset` 方法。 - -### SetIcon - -API:`SetIcon(icon []byte) *SystemTray` - -`SetIcon` 方法设置系统托盘的图标。 - -### SetDarkModeIcon - -API:`SetDarkModeIcon(icon []byte) *SystemTray` - -`SetDarkModeIcon` 方法设置暗黑模式下系统托盘的图标。 - -### SetMenu - -API:`SetMenu(menu *Menu) *SystemTray` - -`SetMenu` 方法设置系统托盘的菜单。 - -### Destroy - -API:`Destroy()` - -`Destroy` 方法销毁系统托盘实例。 - -### OnClick - -API:`OnClick(handler func()) *SystemTray` - -`OnClick` 方法设置点击托盘图标时执行的函数。 - -### OnRightClick - -API:`OnRightClick(handler func()) *SystemTray` - -`OnRightClick` 方法设置右键点击托盘图标时执行的函数。 - -### OnDoubleClick - -API:`OnDoubleClick(handler func()) *SystemTray` - -`OnDoubleClick` 方法设置双击托盘图标时执行的函数。 - -### OnRightDoubleClick - -API:`OnRightDoubleClick(handler func()) *SystemTray` - -`OnRightDoubleClick` 方法设置右键双击托盘图标时执行的函数。 - -### AttachWindow - -API:`AttachWindow(window *WebviewWindow) *SystemTray` - -`AttachWindow` 方法将窗口附加到系统托盘。当点击系统托盘图标时,窗口将显示出来。 - -### WindowOffset - -API:`WindowOffset(offset int) *SystemTray` - -`WindowOffset` 方法设置系统托盘与窗口之间的像素间隔。 - -### WindowDebounce - -API:`WindowDebounce(debounce time.Duration) *SystemTray` - -`WindowDebounce` 方法设置防抖时间。在 Windows 上,它用于指定在响应通知图标上的鼠 -标松开事件之前等待多长时间。 - -### OpenMenu - -API:`OpenMenu()` - -`OpenMenu` 方法打开与系统托盘关联的菜单。 diff --git a/mkdocs-website/docs/zh/API/window.md b/mkdocs-website/docs/zh/API/window.md deleted file mode 100644 index 256ac490c0e..00000000000 --- a/mkdocs-website/docs/zh/API/window.md +++ /dev/null @@ -1,106 +0,0 @@ -# 窗口 - -要创建一个窗口,可以使 -用[Application.NewWebviewWindow](application.md#newwebviewwindow)或[Application.NewWebviewWindowWithOptions](application.md#newwebviewwindowwithoptions)。 -前者创建一个具有默认选项的窗口,而后者允许您指定自定义选项。 - -这些方法可在返回的WebviewWindow对象上调用: - -### SetTitle - -API: `SetTitle(title string) *WebviewWindow` - -此方法将窗口标题更新为提供的字符串。它返回WebviewWindow对象,允许进行方法链接。 - -### Name - -API: `Name() string` - -此函数返回WebviewWindow的名称。 - -### SetSize - -API: `SetSize(width, height int) *WebviewWindow` - -此方法将WebviewWindow的大小设置为提供的宽度和高度参数。如果提供的尺寸超过约束条 -件,它们将被相应调整。 - -### SetAlwaysOnTop - -API: `SetAlwaysOnTop(b bool) *WebviewWindow` - -此函数根据提供的布尔标志设置窗口始终置顶。 - -### Show - -API: `Show() *WebviewWindow` - -`Show`方法用于使窗口可见。如果窗口未运行,它首先调用`run`方法启动窗口,然后使其 -可见。 - -### Hide - -API: `Hide() *WebviewWindow` - -`Hide`方法用于隐藏窗口。它将窗口的隐藏状态设置为true,并触发窗口隐藏事件。 - -### SetURL - -API: `SetURL(s string) *WebviewWindow` - -`SetURL`方法用于将窗口的URL设置为给定的URL字符串。 - -### SetZoom - -API: `SetZoom(magnification float64) *WebviewWindow` - -`SetZoom`方法将窗口内容的缩放级别设置为提供的放大倍数。 - -### GetZoom - -API: `GetZoom() float64` - -`GetZoom`函数返回窗口内容的当前缩放级别。 - -### GetScreen - -API: `GetScreen() (*Screen, error)` - -`GetScreen`方法返回窗口所显示的屏幕。 - -#### SetFrameless - -API: `SetFrameless(frameless bool) *WebviewWindow` - -此函数用于移除窗口边框和标题栏。它根据提供的布尔值(true表示无边框,false表示有 -边框)切换窗口的无边框状态。 - -#### RegisterContextMenu - -API: `RegisterContextMenu(name string, menu *Menu)` - -此函数用于注册上下文菜单并为其指定给定的名称。 - -#### NativeWindowHandle - -API: `NativeWindowHandle() (uintptr, error)` - -此函数用于获取窗口的平台本机窗口句柄。 - -#### Focus - -API: `Focus()` - -此函数用于将焦点设置到窗口。 - -#### SetEnabled - -API: `SetEnabled(enabled bool)` - -此函数用于根据提供的布尔值启用/禁用窗口。 - -#### SetAbsolutePosition - -API: `SetAbsolutePosition(x int, y int)` - -此函数设置窗口在屏幕上的绝对位置。 diff --git a/mkdocs-website/docs/zh/changelog.md b/mkdocs-website/docs/zh/changelog.md deleted file mode 100644 index bcd1a9bb4ce..00000000000 --- a/mkdocs-website/docs/zh/changelog.md +++ /dev/null @@ -1,44 +0,0 @@ -# 更新日志 - - - -## [未发布] - -### Added - -- [darwin] 添加Event ApplicationShouldHandleReopen以处理单击dock图标的功能 - @5aaee9 in [#2991](https://github.com/wailsapp/wails/pull/2991) -- [darwin] 添加getPrimaryScreen/getScreens的实现 @tmclane in - [#2618](https://github.com/wailsapp/wails/pull/2618) - -### Fixed - -- 修复Doctor apt软件包验证问题 [Atterpac](https://github.com/Atterpac) in - [#2972](https://github.com/wailsapp/wails/pull/2972)。 -- 修复应用程序在退出时冻结的问题 (Darwin) @5aaee9 in - [#2982](https://github.com/wailsapp/wails/pull/2982) -- 修复Windows上示例的背景颜色问题 [mmgvh](https://github.com/mmghv) in - [#2750](https://github.com/wailsapp/wails/pull/2750)。 -- 修复默认上下文菜单问题 [mmgvh](https://github.com/mmghv) in - [#2753](https://github.com/wailsapp/wails/pull/2753)。 - -### Changed - -### Removed - -### Deprecated - -### Security diff --git a/mkdocs-website/docs/zh/development/changes.md b/mkdocs-website/docs/zh/development/changes.md deleted file mode 100644 index f830d67ef32..00000000000 --- a/mkdocs-website/docs/zh/development/changes.md +++ /dev/null @@ -1,402 +0,0 @@ -# v3的更改 - -!!! note这是当前的无序更改脑升级。很快它将组织成一个更易读的格式。 - -## 选项 - -自v2以来,应用程序选项已经进行了修订。 - -## 事件 - -在v3中,有3种类型的事件: - -- 应用程序事件 -- 窗口事件 -- 自定义事件 - -### 应用程序事件 - -应用程序事件是由应用程序发出的事件。这些事件包括macOS上 -的`ApplicationDidFinishLaunching`等本机事件。 - -### 窗口事件 - -窗口事件是由窗口发出的事件。这些事件包括macOS上的`WindowDidBecomeMain`等本机事 -件。还定义了常见事件,以便它们在跨平台上工作,例如`WindowClosing`。 - -### 自定义事件 - -用户定义的事件称为`WailsEvents`。这是为了将它们与用于与浏览器通信的`Event`对象区 -分开来。WailsEvents现在是封装事件的对象。这包括事件名称,数据和事件的源。 - -与WailsEvent关联的数据现在是单个值。如果需要多个值,则可以使用struct。 - -### 事件回调和`Emit`函数签名 - -事件回调的签名(由`On`,`Once`和`OnMultiple`使用)已更改。在v2中,回调函数接收可 -选数据。在v3中,回调函数接收包含与事件相关的所有数据的`WailsEvent`对象。 - -类似地,`Emit`函数已更改。它现在不再接受名称和可选数据,而是接受一 -个`WailsEvent`对象,它将发出该对象。 - -### `Off`和`OffAll` - -在v2中,`Off`和`OffAll`调用将删除JS和Go中的事件。由于v3具有多窗口的特性,因此已 -更改为这些方法仅适用于调用它们的上下文。例如,如果你在一个窗口中调用`Off`,它仅 -会删除该窗口的事件。如果你在Go中使用`Off`,它只会删除Go的事件。 - -### Hooks - -事件钩子是v3中的新功能。它们允许您钩入事件系统,并在发出某些事件时执行操作。例 -如,您可以钩入`WindowClosing`事件,在窗口关闭之前执行一些清理操作。钩子可以在应 -用程序级别或窗口级别使用`RegisterHook`进行注册。应用程序级别适用于应用程序事件。 -仅当窗口级别钩子与其注册的窗口一起调用。 - -### 日志记录 - -在v2中,日志记录会混淆,因为应用程序日志和系统(内部)日志都使用相同的记录器。我 -们已经对此进行了简化: - -- 内部日志现在使用标准的Go `slog`记录器处理。这是通过应用程序选项中的`logger`选 - 项进行配置的。默认情况下,这使用[tint](https://github.com/lmittmann/tint)记录 - 器。 -- 现在可以通过新的`log`插件进行应用程序日志记录,它在底层使用`slog`。此插件提供 - 了一个简单的用于记录到控制台的API。它在Go和JS中都可用。 - -### 开发人员注意事项 - -在Go中发出事件时,它会将事件分派到本地的Go侦听器以及应用程序中的每个窗口。在JS中 -发出事件时,它现在会将事件发送到应用程序。这将被处理,就好像它是在Go中发出的,但 -是发送者ID将是窗口的ID。 - -## 窗口 - -Window API在很大程度上保持不变,但方法现在是在窗口实例而不是运行时上。一些值得注 -意的变化是: - -- 窗口现在具有标识它们的名称。用于在发出事件时标识窗口。 -- 窗口上现在有更多以前不可用的方法,例如`AbsolutePosition`和`ToggleDevTools`。 -- 窗口现在可以通过本机拖放接受文件。有关详细信息,请参阅拖放部分。 - -## 剪切板 - -剪贴板API已经简化。现在有一个单独的`Clipboard`对象,可以用于读取和写入剪贴 -板。`Clipboard`对象在Go和JS中都可用。`SetText()`用于设置文本,`Text()`用于获取文 -本。 - -## 绑定 - -绑定的工作方式与v2类似,通过提供一种将结构方法绑定到前端的方式。这些可以在前端使 -用由`wails3 generate bindings`命令生成的绑定包装器来调用: - -```javascript -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import { main } from "./models"; - -window.go = window.go || {}; -window.go.main = { - GreetService: { - /** - * GreetService.Greet - * Greet greets a person - * @param name {string} - * @returns {Promise} - **/ - Greet: function (name) { - wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); - }, - - /** - * GreetService.GreetPerson - * GreetPerson greets a person - * @param person {main.Person} - * @returns {Promise} - **/ - GreetPerson: function (person) { - wails.CallByID(4021313248, ...Array.prototype.slice.call(arguments, 0)); - }, - }, -}; -``` - -默认情况下,绑定的方法是混淆的,并使用uint32 ID进行标识,该ID是使 -用[FNV哈希算法](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function)计 -算的。这是为了防止方法名称在生产构建中被暴露出来。在调试模式下,方法ID与计算的方 -法ID一起记录,以帮助调试。如果您希望增加额外的混淆层,可以使用`BindAliases`选 -项。这允许您指定别名ID与方法ID的映射。当前端使用ID调用方法时,方法ID将首先在别名 -映射中查找匹配项。如果找不到,它将假定是标准方法ID,并尝试以通常的方式查找方法。 - -示例: - -```go - app := application.New(application.Options{ - Bind: []any{ - &GreetService{}, - }, - BindAliases: map[uint32]uint32{ - 1: 1411160069, - 2: 4021313248, - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) -``` - -现在我们可以使用此别名在前端调用:`wails.Call(1, "world!")`。 - -### 不安全调用 - -如果您不介意在二进制文件中以明文形式提供调用,并且不打算使 -用[garble](https://github.com/burrowers/garble),那么可以使用不安全 -的`wails.CallByName()`方法。此方法接受要调用的方法的完全限定名称和要传递给它的参 -数。示例: - - ```go - wails.CallByName("main.GreetService.Greet", "world!") - ``` - -!!! danger - - 这仅作为开发的便利方法提供。不建议在生产中使用此方法。 - -## 对话框 - -对话框现在在JavaScript中可用! - -### Windows - -Windows中的对话框按钮是不可配置的,根据对话框的类型是恒定的。要在按下按钮时触发 -回调,请创建一个具有与您希望附加回调的按钮相同名称的按钮。示例:创建一个标签为“ -确定”的按钮,并使用`OnClick()`方法设置回调方法: - -```go - dialog := app.QuestionDialog(). - SetTitle("Update"). - SetMessage("The cancel button is selected when pressing escape") - ok := dialog.AddButton("Ok") - ok.OnClick(func() { - // Do something - }) - no := dialog.AddButton("Cancel") - dialog.SetDefaultButton(ok) - dialog.SetCancelButton(no) - dialog.Show() -``` - -## 拖放 - -可以按窗口启用本机拖放。只需将`EnableDragAndDrop`窗口配置选项设置为`true`,窗口 -将允许将文件拖放到其上。当这种情况发生时,将发出`events.FilesDropped`事件。然后 -可以使用`WindowEvent.Context()`中的`DroppedFiles()`方法检索文件名。这将返回一个 -包含文件名的字符串切片。 - -## 上下文菜单 - -上下文菜单是当用户右键单击元素时显示的上下文菜单。创建上下文菜单与创建标准菜单相 -同,使用`app.NewMenu()`。要使上下文菜单对窗口可用,请调 -用`window.RegisterContextMenu(name, menu)`。名称将是上下文菜单的ID,并由前端使 -用。 - -要指示元素具有上下文菜单,请将`data-contextmenu`属性添加到元素。此属性的值应为先 -前在窗口中注册的上下文菜单的名称。 - -可以在应用程序级别注册上下文菜单,使其对所有窗口可用。可以使 -用`app.RegisterContextMenu(name, menu)`完成此操作。如果在窗口级别找不到上下文菜 -单,则将检查应用程序上下文菜单。`v3/examples/contextmenus`中可以找到此演示。 - -## Wails标记语言(WML) - -Wails标记语言是一种简单的标记语言,允许您在没有JavaScript的情况下向标准HTML元素 -添加功能。 - -当前支持以下标签: - -### `data-wml-event` - -这指定单击元素时将发出Wails事件。属性的值应为要发出的事件的名称。 - -示例: - -```html - -``` - -有时您需要用户确认操作。可以通过向元素添加`data-wml-confirm`属性来完成。此属性的 -值将是要显示给用户的消息。 - -示例: - -```html - -``` - -### `data-wml-window` - -可以通过将`data-wml-window`属性添加到元素中来调用任何`wails.window`方法。属性的 -值应为要调用的方法的名称。方法名称应与导出的方法的名称完全匹配。 - -```html - -``` - -### `data-wml-trigger` - -此属性指定应触发操作的javascript事件。默认为`click`。 - -```html - -``` - -## 系统托盘 - -Wails 3附带了一个内置的系统托盘。这是一个完全功能的系统托盘,旨在尽可能简单地使 -用。可以设置托盘的图标、工具提示和菜单。还可以“附加”窗口到系统托盘。这样做将提供 -以下功能: - -- 单击托盘图标会切换窗口可见性 -- 右键单击托盘将打开菜单(如果有) - -在macOS上,如果没有附加的窗口,则托盘将使用显示菜单的默认方法(任何按钮)。如果 -有附加的窗口但没有菜单,则托盘将切换窗口,而不管按下的按钮如何。 - -## 插件 - -插件是扩展Wails应用程序功能的一种方式。 - -### 创建插件 - -插件是符合以下接口的标准Go结构: - -```go -type Plugin interface { - Name() string - Init(*application.App) error - Shutdown() - CallableByJS() []string - InjectJS() string -} -``` - -`Name()`方法返回插件的名称。这用于记录目的。 - -`Init(*application.App) error`方法在加载插件时调用。`*application.App`参数是加载 -插件的应用程序。任何错误都将阻止应用程序启动。 - -`Shutdown()`方法在应用程序关闭时调用。 - -`CallableByJS()`方法返回可以从前端调用的导出函数列表。这些方法名称必须与插件导出 -的方法名称完全匹配。 - -`InjectJS()`方法返回应注入到创建的所有窗口中的JavaScript。这对于添加与插件补充的 -自定义JavaScript函数很有用。 - -### 提示 - -#### 枚举 - -在Go中,枚举通常被定义为类型和一组常量。例如: - -```go -type MyEnum int - -const ( - MyEnumOne MyEnum = iota - MyEnumTwo - MyEnumThree -) -``` - -由于Go和JavaScript之间的不兼容性,无法以这种方式使用自定义类型。最好的策略是为 -float64使用类型别名: - -```go -type MyEnum = float64 - -const ( - MyEnumOne MyEnum = iota - MyEnumTwo - MyEnumThree -) -``` - -在Javascript中,您可以使用以下代码: - -```js -const MyEnum = { - MyEnumOne: 0, - MyEnumTwo: 1, - MyEnumThree: 2, -}; -``` - -- 为什么使用`float64`?不能使用`int`吗? - - 因为JavaScript没有“int”的概念。一切都是`number`,在Go中会转换为`float64`。Go - 的反射包中还有类型转换的限制,这意味着使用`int`是行不通的。 - -### BackgroundColour - -在v2中,这是指向`RGBA`结构的指针。在v3中,这是`RGBA`结构的值。 - -### WindowIsTranslucent - -已删除此标志。现在有一个`BackgroundType`标志,可用于设置窗口应具有的背景类型。此 -标志可以设置为以下任何值: - -- `BackgroundTypeSolid` - 窗口将具有实心背景 -- `BackgroundTypeTransparent` - 窗口将具有透明背景 -- `BackgroundTypeTranslucent` - 窗口将具有半透明背景 - -在Windows上,如果`BackgroundType`设置为`BackgroundTypeTranslucent`,则可以使 -用`WindowsWindow`选项中的`BackdropType`标志设置透明度的类型。这可以设置为以下任 -何值: - -- `Auto` - 窗口将使用系统确定的效果 -- `None` - 窗口没有背景 -- `Mica` - 窗口使用Mica效果 -- `Acrylic` - 窗口使用丙烯酸效果 -- `Tabbed` - 窗口使用选项卡效果 - -## Windows Application Options - -### WndProcInterceptor - -如果设置了此标志,将拦截WndProc并调用该函数。这允许您直接处理Windows消息。该函数 -应具有以下签名: - -```go -func(hwnd uintptr, msg uint32, wParam, lParam uintptr) (returnValue uintptr, shouldReturn) -``` - -如果`shouldReturn`值设置为`true`,则`returnValue`将由主wndProc方法返回。如果设置 -为`false`,将忽略返回值,并且消息将继续由主wndProc方法处理。 - -## 在关闭时隐藏窗口+OnBeforeClose - -在v2中,有一个`HideWindowOnClose`标志,用于在关闭窗口时隐藏窗 -口。`HideWindowOnClose`标志与`OnBeforeClose`回调之间存在逻辑重叠。在v3中,已删 -除`HideWindowOnClose`标志,并将`OnBeforeClose`回调重命名为`ShouldClose`。当用户 -尝试关闭窗口时,将调用`ShouldClose`回调。如果回调返回`true`,窗口将关闭。如果返 -回`false`,窗口将不会关闭。这可以用于隐藏窗口而不是关闭窗口。 - -## 窗口拖动 - -在v2中,使用`--wails-drag`属性来指示可以使用元素拖动窗口。在v3中,已将其替换 -为`--webkit-app-region`,以更符合其他框架处理方式。`--webkit-app-region`属性可以 -设置为以下任何值: - -- `drag` - 可使用该元素拖动窗口 -- `no-drag` - 该元素无法用于拖动窗口 - -我们本来希望使用`app-region`,但是在webkit在macOS上的`getComputedStyle`调用不支 -持它。 diff --git a/mkdocs-website/docs/zh/development/introduction.md b/mkdocs-website/docs/zh/development/introduction.md deleted file mode 100644 index d0f8bf4063d..00000000000 --- a/mkdocs-website/docs/zh/development/introduction.md +++ /dev/null @@ -1,185 +0,0 @@ -# 介绍 - -!!! note 这个指南仍在制作中。 - -感谢您想要帮助开发Wails!本指南将帮助您入门。 - -## 入门指南 - -- Git 克隆此存储库。切换到 `v3-alpha` 分支。 -- 安装 CLI:`cd v3/cmd/wails3 && go install` - -- 可选:如果您想要使用构建系统构建前端代码,您需要安装 - [npm](https://nodejs.org/en/download)。 - -## 构建 - -对于简单的程序,您可以使用标准的 `go build` 命令。也可以使用 `go run`。 - -Wails 还配备了一个构建系统,可用于构建更复杂的项目。它使用了强大的 -[Task](https://taskfile.dev) 构建系统。要了解更多信息,请查看任务主页或运行 -`wails task --help`。 - -## 项目结构 - -该项目具有以下结构: - - ``` - v3 - ├── cmd/wails3 // CLI - ├── examples // Wails 应用示例 - ├── internal // 内部包 - | ├── runtime // Wails JS 运行时 - | └── templates // 支持的项目模板 - ├── pkg - | ├── application // 核心 Wails 库 - | └── events // 事件定义 - | └── mac // 由插件使用的 macOS 特定代码 - | └── w32 // Windows 特定代码 - ├── plugins // 支持的插件 - ├── tasks // 通用任务 - └── Taskfile.yaml // 开发任务配置 - ``` - -## 开发 - -### 添加窗口功能 - -添加窗口功能的首选方法是在 `pkg/application/webview_window.go` 文件中添加一个新 -函数。这应该实现所有平台所需的功能。任何特定于平台的代码都应通过 -`webviewWindowImpl` 接口方法调用。该接口由每个目标平台实现,以提供平台特定的功 -能。在某些情况下,这可能不执行任何操作。添加接口方法后,请确保每个平台都实现了 -它。一个很好的例子是 `SetMinSize` 方法。 - -- Mac: `webview_window_darwin.go` -- Windows: `webview_window_windows.go` -- Linux: `webview_window_linux.go` - -大多数,如果不是全部,特定于平台的代码应在主线程上运行。为了简化这一点,在 -`application.go` 中定义了一些 `invokeSync` 方法。 - -### 更新运行时 - -运行时位于 `v3/internal/runtime`。更新运行时时,需要执行以下步骤: - -```shell -wails3 task runtime:build -``` - -### 事件 - -事件定义在 `v3/pkg/events` 中。当添加新事件时,需要执行以下步骤: - -- 将事件添加到 `events.txt` 文件中 -- 运行 `wails3 task events:generate` - -有几种类型的事件:特定于平台的应用程序和窗口事件 + 通用事件。通用事件对于跨平台 -事件处理很有用,但您不必局限于“最低公共分母”。如果需要,可以使用特定于平台的事 -件。 - -添加通用事件时,请确保映射了特定于平台的事件。一个示例是在 -`window_webview_darwin.go` 中: - -```go - // 将 ShouldClose 转化为通用的 WindowClosing 事件 - w.parent.On(events.Mac.WindowShouldClose, func(_ *WindowEventContext) { - w.parent.emit(events.Common.WindowClosing) - }) -``` - -注意:我们可能会尝试通过将映射添加到事件定义中来自动化此过程。 - -### 插件 - -插件是扩展 Wails 应用功能的一种方式。 - -#### 创建插件 - -插件是符合以下接口的标准 Go 结构: - -```go -type Plugin interface { - Name() string - Init(*application.App) error - Shutdown() - CallableByJS() []string - InjectJS() string -} -``` - -`Name()` 方法返回插件的名称。这用于日志记录。 - -`Init(*application.App) error` 方法在加载插件时调用。`*application.App` 参数是加 -载插件的应用程序。任何错误都将阻止应用程序启动。 - -`Shutdown()` 方法在应用程序关闭时调用。 - -`CallableByJS()` 方法返回可以从前端调用的导出函数列表。这些方法的名称必须与插件 -导出的方法的名称完全匹配。 - -`InjectJS()` 方法返回应注入到所有窗口中的 JavaScript。这对于添加与插件相补充的自 -定义 JavaScript 函数非常有用。 - -内置插件可以在 `v3/plugins` 目录中找到。参考它们以获得灵感。 - -## 任务 - -Wails CLI 使用 [Task](https://taskfile.dev) 构建系统。它作为库导入并用于运行 -`Taskfile.yaml` 中定义的任务。与 Task 的主要交互发生在 -`v3/internal/commands/task.go` 中。 - -### 升级 Taskfile - -要检查是否有 Taskfile 的升级,请运行 `wails3 task -version` 并检查 Task 网站。 - -要升级使用的 Taskfile 版本,请运行: - -```shell -wails3 task taskfile:upgrade -``` - -如果存在不兼容性,则应在 `v3/internal/commands/task.go` 文件中显示。 - -通常,修复不兼容性的最佳方法是克隆 `https://github.com/go-task/task` 上的任务存 -储库,并查看 git 历史记录以确定发生了什么变化以及原因。 - -要检查所有更改是否正确工作,请重新安装 CLI 并再次检查版本: - -```shell -wails3 task cli:install -wails3 task -version -``` - -## 打开 PR - -确保所有 PR 都有与之关联的工单,以提供更改的上下文。如果没有工单,请先创建一个。 -确保所有 PR 都已使用所做的更改更新了 CHANGELOG.md 文件。CHANGELOG.md 文件位于 -`mkdocs-website/docs` 目录中。 - -## 其他任务 - -### 升级 Taskfile - -Wails CLI 使用 [Task](https://taskfile.dev) 构建系统。它作为库导入并用于运行 -`Taskfile.yaml` 中定义的任务。与 Task 的主要交互发生在 -`v3/internal/commands/task.go` 中。 - -要检查是否有 Taskfile 的升级,请运行 `wails3 task -version` 并检查 Task 网站。 - -要升级使用的 Taskfile 版本,请运行: - -```shell -wails3 task taskfile:upgrade -``` - -如果存在不兼容性,则应在 `v3/internal/commands/task.go` 文件中显示。 - -通常,修复不兼容性的最佳方法是克隆 `https://github.com/go-task/task` 上的任务存 -储库,并查看 git 历史记录以确定发生了什么变化以及原因。 - -要检查所有更改是否正确工作,请重新安装 CLI 并再次检查版本: - -```shell -wails3 task cli:install -wails3 task -version -``` diff --git a/mkdocs-website/docs/zh/development/status.md b/mkdocs-website/docs/zh/development/status.md deleted file mode 100644 index 75eed8a14f8..00000000000 --- a/mkdocs-website/docs/zh/development/status.md +++ /dev/null @@ -1,382 +0,0 @@ -将以下文本翻译为中文,并不要翻译 `!!! note` 或 `!!! tip` 或以此格式的字符串: - -# 状态 - -v3版功能的状态。 - -!!! note - - 此列表包含公有和内部API支持的混合内容。
- 它不完整且可能不是最新的。 - -## 已知问题 - -- Linux尚未与Windows/Mac达到功能平衡 - -## 应用程序 - -应用程序接口方法 - -| 方法 | Windows | Linux | Mac | 备注 | -| ------------------------------------------------------------- | ------- | ----- | --- | ---- | -| run() error | Y | Y | Y | | -| destroy() | | Y | Y | | -| setApplicationMenu(menu \*Menu) | Y | Y | Y | | -| name() string | | Y | Y | | -| getCurrentWindowID() uint | Y | Y | Y | | -| showAboutDialog(name string, description string, icon []byte) | | Y | Y | | -| setIcon(icon []byte) | - | Y | Y | | -| on(id uint) | | | Y | | -| dispatchOnMainThread(fn func()) | Y | Y | Y | | -| hide() | Y | Y | Y | | -| show() | Y | Y | Y | | -| getPrimaryScreen() (\*Screen, error) | | Y | Y | | -| getScreens() ([]\*Screen, error) | | Y | Y | | - -## Webview 窗口 - -Webview 窗口接口方法 - -| 方法 | Windows | Linux | Mac | 备注 | -| -------------------------------------------------- | ------- | ----- | --- | -------------------- | -| center() | Y | Y | Y | | -| close() | y | Y | Y | | -| destroy() | | Y | Y | | -| execJS(js string) | y | Y | Y | | -| focus() | Y | Y | | | -| forceReload() | | Y | Y | | -| fullscreen() | Y | Y | Y | | -| getScreen() (\*Screen, error) | y | Y | Y | | -| getZoom() float64 | | Y | Y | | -| height() int | Y | Y | Y | | -| hide() | Y | Y | Y | | -| isFullscreen() bool | Y | Y | Y | | -| isMaximised() bool | Y | Y | Y | | -| isMinimised() bool | Y | Y | Y | | -| maximise() | Y | Y | Y | | -| minimise() | Y | Y | Y | | -| nativeWindowHandle() (uintptr, error) | Y | Y | | | -| on(eventID uint) | y | | Y | | -| openContextMenu(menu *Menu, data *ContextMenuData) | y | | Y | | -| relativePosition() (int, int) | Y | Y | Y | | -| reload() | y | Y | Y | | -| run() | Y | Y | Y | | -| setAlwaysOnTop(alwaysOnTop bool) | Y | Y | Y | | -| setBackgroundColour(color RGBA) | Y | Y | Y | | -| setEnabled(bool) | | Y | Y | | -| setFrameless(bool) | | Y | Y | | -| setFullscreenButtonEnabled(enabled bool) | - | Y | Y | Windows 没有全屏按钮 | -| setHTML(html string) | Y | Y | Y | | -| setMaxSize(width, height int) | Y | Y | Y | | -| setMinSize(width, height int) | Y | Y | Y | | -| setRelativePosition(x int, y int) | Y | Y | Y | | -| setResizable(resizable bool) | Y | Y | Y | | -| setSize(width, height int) | Y | Y | Y | | -| setTitle(title string) | Y | Y | Y | | -| setURL(url string) | Y | Y | Y | | -| setZoom(zoom float64) | Y | Y | Y | | -| show() | Y | Y | Y | | -| size() (int, int) | Y | Y | Y | | -| toggleDevTools() | Y | Y | Y | | -| unfullscreen() | Y | Y | Y | | -| unmaximise() | Y | Y | Y | | -| unminimise() | Y | Y | Y | | -| width() int | Y | Y | Y | | -| zoom() | | Y | Y | | -| zoomIn() | Y | Y | Y | | -| zoomOut() | Y | Y | Y | | -| zoomReset() | Y | Y | Y | | - -## 运行时 - -### 应用程序 - -| 功能 | Windows | Linux | Mac | 备注 | -| ---- | ------- | ----- | --- | ---- | -| 退出 | Y | Y | Y | | -| 隐藏 | Y | | Y | | -| 显示 | Y | | Y | | - -### 对话框 - -| 功能 | Windows | Linux | Mac | 备注 | -| -------- | ------- | ----- | --- | ---- | -| 信息 | Y | Y | Y | | -| 警告 | Y | Y | Y | | -| 错误 | Y | Y | Y | | -| 问题 | Y | Y | Y | | -| 打开文件 | Y | | Y | | -| 保存文件 | Y | | Y | | - -### 剪贴板 - -| 功能 | Windows | Linux | Mac | 备注 | -| -------- | ------- | ----- | --- | ---- | -| 设置文本 | Y | | Y | | -| 文本 | Y | | Y | | - -### 上下文菜单 - -| 功能 | Windows | Linux | Mac | 备注 | -| -------------- | ------- | ----- | --- | ---- | -| 打开上下文菜单 | Y | | Y | | -| 默认开启 | | | | | -| 通过 HTML 控制 | Y | | | | - -默认上下文菜单默认对所有`contentEditable: true`、``或`