From bd94be0d9a8792b05eeda2302d4cab3fbcb5afe3 Mon Sep 17 00:00:00 2001 From: taliesin Date: Mon, 11 May 2026 02:08:25 +1000 Subject: [PATCH] i18n(pt): add Portuguese translations 2026-05-11 --- docs/.translation-cache/pt.json | 418 ++++++- docs/src/content/docs/pt/community/links.md | 28 + .../content/docs/pt/community/templates.md | 131 +++ .../content/docs/pt/concepts/architecture.mdx | 328 ++++++ docs/src/content/docs/pt/concepts/bridge.mdx | 391 +++++++ .../content/docs/pt/concepts/build-system.mdx | 424 +++++++ .../content/docs/pt/concepts/lifecycle.mdx | 368 ++++++ .../content/docs/pt/concepts/manager-api.mdx | 266 +++++ docs/src/content/docs/pt/contributing.mdx | 275 +++++ .../docs/pt/contributing/architecture.mdx | 98 ++ .../pt/contributing/architecture/bindings.mdx | 156 +++ .../docs/pt/contributing/asset-server.mdx | 197 ++++ .../docs/pt/contributing/binding-system.mdx | 239 ++++ .../docs/pt/contributing/build-packaging.mdx | 211 ++++ .../docs/pt/contributing/codebase-layout.mdx | 213 ++++ .../docs/pt/contributing/extending-wails.mdx | 246 ++++ .../docs/pt/contributing/getting-started.mdx | 367 ++++++ .../content/docs/pt/contributing/index.mdx | 94 ++ .../pt/contributing/runtime-internals.mdx | 211 ++++ .../content/docs/pt/contributing/setup.mdx | 297 +++++ .../docs/pt/contributing/standards.mdx | 463 ++++++++ .../docs/pt/contributing/template-system.mdx | 221 ++++ .../docs/pt/contributing/testing-ci.mdx | 215 ++++ docs/src/content/docs/pt/credits.mdx | 60 + docs/src/content/docs/pt/faq.mdx | 260 +++++ .../docs/pt/features/bindings/advanced.mdx | 342 ++++++ .../pt/features/bindings/best-practices.mdx | 365 ++++++ .../docs/pt/features/bindings/enums.mdx | 397 +++++++ .../docs/pt/features/bindings/methods.mdx | 410 +++++++ .../docs/pt/features/bindings/models.mdx | 456 ++++++++ .../docs/pt/features/bindings/services.mdx | 615 ++++++++++ .../docs/pt/features/browser/integration.mdx | 510 +++++++++ .../docs/pt/features/clipboard/basics.mdx | 409 +++++++ .../docs/pt/features/dialogs/custom.mdx | 383 +++++++ .../content/docs/pt/features/dialogs/file.mdx | 330 ++++++ .../docs/pt/features/dialogs/message.mdx | 384 +++++++ .../docs/pt/features/dialogs/overview.mdx | 376 +++++++ .../docs/pt/features/drag-and-drop/files.mdx | 212 ++++ .../docs/pt/features/drag-and-drop/html.mdx | 232 ++++ .../docs/pt/features/environment/info.mdx | 617 ++++++++++ .../docs/pt/features/events/system.mdx | 363 ++++++ .../docs/pt/features/keyboard/shortcuts.mdx | 437 +++++++ .../docs/pt/features/menus/application.mdx | 508 +++++++++ .../docs/pt/features/menus/context.mdx | 643 +++++++++++ .../docs/pt/features/menus/reference.mdx | 359 ++++++ .../docs/pt/features/menus/systray.mdx | 388 +++++++ .../pt/features/notifications/overview.mdx | 303 +++++ .../docs/pt/features/platform/dock.mdx | 241 ++++ .../content/docs/pt/features/screens/info.mdx | 343 ++++++ .../docs/pt/features/windows/basics.mdx | 417 +++++++ .../docs/pt/features/windows/events.mdx | 422 +++++++ .../docs/pt/features/windows/frameless.mdx | 789 +++++++++++++ .../docs/pt/features/windows/multiple.mdx | 606 ++++++++++ .../docs/pt/features/windows/options.mdx | 1001 +++++++++++++++++ docs/src/content/docs/pt/feedback.mdx | 86 ++ .../pt/getting-started/your-first-app.mdx | 270 +++++ .../content/docs/pt/guides/architecture.mdx | 199 ++++ .../content/docs/pt/guides/build/building.mdx | 121 ++ .../docs/pt/guides/build/cross-platform.mdx | 296 +++++ .../docs/pt/guides/build/customization.mdx | 270 +++++ .../content/docs/pt/guides/build/linux.mdx | 223 ++++ .../content/docs/pt/guides/build/macos.mdx | 145 +++ .../content/docs/pt/guides/build/signing.mdx | 684 +++++++++++ .../content/docs/pt/guides/build/windows.mdx | 124 ++ docs/src/content/docs/pt/guides/cli.mdx | 551 +++++++++ .../docs/pt/guides/custom-templates.mdx | 286 +++++ .../docs/pt/guides/custom-transport.mdx | 172 +++ .../docs/pt/guides/customising-windows.mdx | 129 +++ .../pt/guides/distribution/auto-updates.mdx | 562 +++++++++ .../guides/distribution/custom-protocols.mdx | 613 ++++++++++ .../content/docs/pt/guides/e2e-testing.mdx | 173 +++ .../docs/pt/guides/events-reference.mdx | 459 ++++++++ .../docs/pt/guides/file-associations.mdx | 178 +++ .../content/docs/pt/guides/gin-routing.mdx | 263 +++++ .../content/docs/pt/guides/gin-services.mdx | 554 +++++++++ .../src/content/docs/pt/guides/installers.mdx | 160 +++ docs/src/content/docs/pt/guides/menus.mdx | 524 +++++++++ .../content/docs/pt/guides/panic-handling.mdx | 116 ++ .../content/docs/pt/guides/performance.mdx | 341 ++++++ .../content/docs/pt/guides/raw-messages.mdx | 391 +++++++ docs/src/content/docs/pt/guides/routing.mdx | 110 ++ docs/src/content/docs/pt/guides/security.mdx | 261 +++++ .../content/docs/pt/guides/server-build.mdx | 312 +++++ .../docs/pt/guides/single-instance.mdx | 119 ++ docs/src/content/docs/pt/guides/testing.mdx | 175 +++ .../content/docs/pt/guides/windows-uac.mdx | 152 +++ .../content/docs/pt/migration/v2-to-v3.mdx | 670 +++++++++++ .../content/docs/pt/quick-start/first-app.mdx | 270 +++++ .../docs/pt/quick-start/installation.mdx | 327 ++++++ .../content/docs/pt/reference/application.mdx | 486 ++++++++ docs/src/content/docs/pt/reference/cli.mdx | 28 + .../src/content/docs/pt/reference/dialogs.mdx | 831 ++++++++++++++ docs/src/content/docs/pt/reference/events.mdx | 737 ++++++++++++ .../docs/pt/reference/frontend-runtime.mdx | 943 ++++++++++++++++ docs/src/content/docs/pt/reference/menu.mdx | 722 ++++++++++++ .../content/docs/pt/reference/overview.mdx | 282 +++++ .../src/content/docs/pt/reference/updater.mdx | 501 +++++++++ docs/src/content/docs/pt/reference/window.mdx | 503 +++++++++ .../docs/pt/troubleshooting/mac-syso.mdx | 23 + .../pt/tutorials/01-creating-a-service.mdx | 710 ++++++++++++ .../docs/pt/tutorials/02-todo-vanilla.mdx | 721 ++++++++++++ .../docs/pt/tutorials/03-notes-vanilla.mdx | 701 ++++++++++++ .../content/docs/pt/tutorials/overview.mdx | 84 ++ 103 files changed, 36588 insertions(+), 5 deletions(-) create mode 100644 docs/src/content/docs/pt/community/links.md create mode 100644 docs/src/content/docs/pt/community/templates.md create mode 100644 docs/src/content/docs/pt/concepts/architecture.mdx create mode 100644 docs/src/content/docs/pt/concepts/bridge.mdx create mode 100644 docs/src/content/docs/pt/concepts/build-system.mdx create mode 100644 docs/src/content/docs/pt/concepts/lifecycle.mdx create mode 100644 docs/src/content/docs/pt/concepts/manager-api.mdx create mode 100644 docs/src/content/docs/pt/contributing.mdx create mode 100644 docs/src/content/docs/pt/contributing/architecture.mdx create mode 100644 docs/src/content/docs/pt/contributing/architecture/bindings.mdx create mode 100644 docs/src/content/docs/pt/contributing/asset-server.mdx create mode 100644 docs/src/content/docs/pt/contributing/binding-system.mdx create mode 100644 docs/src/content/docs/pt/contributing/build-packaging.mdx create mode 100644 docs/src/content/docs/pt/contributing/codebase-layout.mdx create mode 100644 docs/src/content/docs/pt/contributing/extending-wails.mdx create mode 100644 docs/src/content/docs/pt/contributing/getting-started.mdx create mode 100644 docs/src/content/docs/pt/contributing/index.mdx create mode 100644 docs/src/content/docs/pt/contributing/runtime-internals.mdx create mode 100644 docs/src/content/docs/pt/contributing/setup.mdx create mode 100644 docs/src/content/docs/pt/contributing/standards.mdx create mode 100644 docs/src/content/docs/pt/contributing/template-system.mdx create mode 100644 docs/src/content/docs/pt/contributing/testing-ci.mdx create mode 100644 docs/src/content/docs/pt/credits.mdx create mode 100644 docs/src/content/docs/pt/faq.mdx create mode 100644 docs/src/content/docs/pt/features/bindings/advanced.mdx create mode 100644 docs/src/content/docs/pt/features/bindings/best-practices.mdx create mode 100644 docs/src/content/docs/pt/features/bindings/enums.mdx create mode 100644 docs/src/content/docs/pt/features/bindings/methods.mdx create mode 100644 docs/src/content/docs/pt/features/bindings/models.mdx create mode 100644 docs/src/content/docs/pt/features/bindings/services.mdx create mode 100644 docs/src/content/docs/pt/features/browser/integration.mdx create mode 100644 docs/src/content/docs/pt/features/clipboard/basics.mdx create mode 100644 docs/src/content/docs/pt/features/dialogs/custom.mdx create mode 100644 docs/src/content/docs/pt/features/dialogs/file.mdx create mode 100644 docs/src/content/docs/pt/features/dialogs/message.mdx create mode 100644 docs/src/content/docs/pt/features/dialogs/overview.mdx create mode 100644 docs/src/content/docs/pt/features/drag-and-drop/files.mdx create mode 100644 docs/src/content/docs/pt/features/drag-and-drop/html.mdx create mode 100644 docs/src/content/docs/pt/features/environment/info.mdx create mode 100644 docs/src/content/docs/pt/features/events/system.mdx create mode 100644 docs/src/content/docs/pt/features/keyboard/shortcuts.mdx create mode 100644 docs/src/content/docs/pt/features/menus/application.mdx create mode 100644 docs/src/content/docs/pt/features/menus/context.mdx create mode 100644 docs/src/content/docs/pt/features/menus/reference.mdx create mode 100644 docs/src/content/docs/pt/features/menus/systray.mdx create mode 100644 docs/src/content/docs/pt/features/notifications/overview.mdx create mode 100644 docs/src/content/docs/pt/features/platform/dock.mdx create mode 100644 docs/src/content/docs/pt/features/screens/info.mdx create mode 100644 docs/src/content/docs/pt/features/windows/basics.mdx create mode 100644 docs/src/content/docs/pt/features/windows/events.mdx create mode 100644 docs/src/content/docs/pt/features/windows/frameless.mdx create mode 100644 docs/src/content/docs/pt/features/windows/multiple.mdx create mode 100644 docs/src/content/docs/pt/features/windows/options.mdx create mode 100644 docs/src/content/docs/pt/feedback.mdx create mode 100644 docs/src/content/docs/pt/getting-started/your-first-app.mdx create mode 100644 docs/src/content/docs/pt/guides/architecture.mdx create mode 100644 docs/src/content/docs/pt/guides/build/building.mdx create mode 100644 docs/src/content/docs/pt/guides/build/cross-platform.mdx create mode 100644 docs/src/content/docs/pt/guides/build/customization.mdx create mode 100644 docs/src/content/docs/pt/guides/build/linux.mdx create mode 100644 docs/src/content/docs/pt/guides/build/macos.mdx create mode 100644 docs/src/content/docs/pt/guides/build/signing.mdx create mode 100644 docs/src/content/docs/pt/guides/build/windows.mdx create mode 100644 docs/src/content/docs/pt/guides/cli.mdx create mode 100644 docs/src/content/docs/pt/guides/custom-templates.mdx create mode 100644 docs/src/content/docs/pt/guides/custom-transport.mdx create mode 100644 docs/src/content/docs/pt/guides/customising-windows.mdx create mode 100644 docs/src/content/docs/pt/guides/distribution/auto-updates.mdx create mode 100644 docs/src/content/docs/pt/guides/distribution/custom-protocols.mdx create mode 100644 docs/src/content/docs/pt/guides/e2e-testing.mdx create mode 100644 docs/src/content/docs/pt/guides/events-reference.mdx create mode 100644 docs/src/content/docs/pt/guides/file-associations.mdx create mode 100644 docs/src/content/docs/pt/guides/gin-routing.mdx create mode 100644 docs/src/content/docs/pt/guides/gin-services.mdx create mode 100644 docs/src/content/docs/pt/guides/installers.mdx create mode 100644 docs/src/content/docs/pt/guides/menus.mdx create mode 100644 docs/src/content/docs/pt/guides/panic-handling.mdx create mode 100644 docs/src/content/docs/pt/guides/performance.mdx create mode 100644 docs/src/content/docs/pt/guides/raw-messages.mdx create mode 100644 docs/src/content/docs/pt/guides/routing.mdx create mode 100644 docs/src/content/docs/pt/guides/security.mdx create mode 100644 docs/src/content/docs/pt/guides/server-build.mdx create mode 100644 docs/src/content/docs/pt/guides/single-instance.mdx create mode 100644 docs/src/content/docs/pt/guides/testing.mdx create mode 100644 docs/src/content/docs/pt/guides/windows-uac.mdx create mode 100644 docs/src/content/docs/pt/migration/v2-to-v3.mdx create mode 100644 docs/src/content/docs/pt/quick-start/first-app.mdx create mode 100644 docs/src/content/docs/pt/quick-start/installation.mdx create mode 100644 docs/src/content/docs/pt/reference/application.mdx create mode 100644 docs/src/content/docs/pt/reference/cli.mdx create mode 100644 docs/src/content/docs/pt/reference/dialogs.mdx create mode 100644 docs/src/content/docs/pt/reference/events.mdx create mode 100644 docs/src/content/docs/pt/reference/frontend-runtime.mdx create mode 100644 docs/src/content/docs/pt/reference/menu.mdx create mode 100644 docs/src/content/docs/pt/reference/overview.mdx create mode 100644 docs/src/content/docs/pt/reference/updater.mdx create mode 100644 docs/src/content/docs/pt/reference/window.mdx create mode 100644 docs/src/content/docs/pt/troubleshooting/mac-syso.mdx create mode 100644 docs/src/content/docs/pt/tutorials/01-creating-a-service.mdx create mode 100644 docs/src/content/docs/pt/tutorials/02-todo-vanilla.mdx create mode 100644 docs/src/content/docs/pt/tutorials/03-notes-vanilla.mdx create mode 100644 docs/src/content/docs/pt/tutorials/overview.mdx diff --git a/docs/.translation-cache/pt.json b/docs/.translation-cache/pt.json index 6a0f8d1471a..085afabd906 100644 --- a/docs/.translation-cache/pt.json +++ b/docs/.translation-cache/pt.json @@ -1,22 +1,430 @@ { "index.mdx": { "hash": "8db97751a16d", - "translated_at": "2026-05-04T00:17:06Z" + "translated_at": "2026-05-05T15:40:55Z" }, "quick-start/why-wails.mdx": { "hash": "053b3578f336", - "translated_at": "2026-05-04T00:17:41Z" + "translated_at": "2026-05-05T15:41:51Z" }, "quick-start/next-steps.mdx": { "hash": "9b4cb8954865", - "translated_at": "2026-05-04T00:17:52Z" + "translated_at": "2026-05-05T15:44:40Z" }, "status.mdx": { "hash": "916ecd7da4d4", - "translated_at": "2026-05-04T00:18:01Z" + "translated_at": "2026-05-05T15:46:23Z" }, "getting-started/installation.mdx": { "hash": "8d33a6a61b02", - "translated_at": "2026-05-04T00:18:29Z" + "translated_at": "2026-05-05T15:48:19Z" + }, + "feedback.mdx": { + "hash": "a66bb5c84083", + "translated_at": "2026-05-07T10:14:29Z" + }, + "credits.mdx": { + "hash": "23aa065f90ef", + "translated_at": "2026-05-07T10:14:48Z" + }, + "community/links.md": { + "hash": "29ee416737c0", + "translated_at": "2026-05-07T10:14:54Z" + }, + "community/templates.md": { + "hash": "ca58feff1eac", + "translated_at": "2026-05-07T10:15:36Z" + }, + "faq.mdx": { + "hash": "eaa8fbfa4acf", + "translated_at": "2026-05-07T10:16:15Z" + }, + "quick-start/first-app.mdx": { + "hash": "c93bc077121b", + "translated_at": "2026-05-07T10:17:10Z" + }, + "getting-started/your-first-app.mdx": { + "hash": "396abb7e4fac", + "translated_at": "2026-05-07T10:18:14Z" + }, + "quick-start/installation.mdx": { + "hash": "87359ef751c8", + "translated_at": "2026-05-07T10:19:53Z" + }, + "concepts/architecture.mdx": { + "hash": "25b91fd732e4", + "translated_at": "2026-05-07T10:22:10Z" + }, + "concepts/bridge.mdx": { + "hash": "a60fbffa68bd", + "translated_at": "2026-05-07T10:24:06Z" + }, + "concepts/lifecycle.mdx": { + "hash": "b6f00029b744", + "translated_at": "2026-05-07T10:26:45Z" + }, + "concepts/manager-api.mdx": { + "hash": "e341d18b7b82", + "translated_at": "2026-05-07T10:27:31Z" + }, + "concepts/build-system.mdx": { + "hash": "fecbef0d115c", + "translated_at": "2026-05-07T10:29:30Z" + }, + "contributing.mdx": { + "hash": "306f4c3d7ea3", + "translated_at": "2026-05-07T10:30:10Z" + }, + "contributing/architecture/bindings.mdx": { + "hash": "1a645275cef3", + "translated_at": "2026-05-07T10:30:52Z" + }, + "contributing/architecture.mdx": { + "hash": "0da96d95fc40", + "translated_at": "2026-05-07T10:31:13Z" + }, + "contributing/asset-server.mdx": { + "hash": "bb202d50ab3d", + "translated_at": "2026-05-07T10:32:05Z" + }, + "contributing/binding-system.mdx": { + "hash": "15a1847702e6", + "translated_at": "2026-05-07T10:32:56Z" + }, + "contributing/build-packaging.mdx": { + "hash": "38819d5bdc3c", + "translated_at": "2026-05-07T10:33:55Z" + }, + "contributing/codebase-layout.mdx": { + "hash": "7f458a077ad7", + "translated_at": "2026-05-07T10:34:50Z" + }, + "contributing/extending-wails.mdx": { + "hash": "f3b3f52588fc", + "translated_at": "2026-05-07T10:35:37Z" + }, + "contributing/getting-started.mdx": { + "hash": "b440f9d48686", + "translated_at": "2026-05-07T10:36:55Z" + }, + "contributing/index.mdx": { + "hash": "6ec1a3542787", + "translated_at": "2026-05-07T10:37:22Z" + }, + "contributing/runtime-internals.mdx": { + "hash": "76e0f9076c9f", + "translated_at": "2026-05-07T10:38:37Z" + }, + "contributing/setup.mdx": { + "hash": "fa6ba1d71330", + "translated_at": "2026-05-07T10:39:22Z" + }, + "contributing/standards.mdx": { + "hash": "dff5cfcb8913", + "translated_at": "2026-05-07T10:40:29Z" + }, + "contributing/template-system.mdx": { + "hash": "694bc43c635b", + "translated_at": "2026-05-07T10:41:17Z" + }, + "contributing/testing-ci.mdx": { + "hash": "dd3e51012196", + "translated_at": "2026-05-07T10:42:02Z" + }, + "features/bindings/advanced.mdx": { + "hash": "dbe24ee2af58", + "translated_at": "2026-05-07T10:43:02Z" + }, + "features/bindings/best-practices.mdx": { + "hash": "24dae313b7f3", + "translated_at": "2026-05-07T10:45:01Z" + }, + "features/bindings/enums.mdx": { + "hash": "190ad53a8c23", + "translated_at": "2026-05-07T10:46:32Z" + }, + "features/bindings/methods.mdx": { + "hash": "81d390a468d6", + "translated_at": "2026-05-07T10:48:16Z" + }, + "features/bindings/models.mdx": { + "hash": "9f9ef8652dfb", + "translated_at": "2026-05-07T10:50:05Z" + }, + "features/bindings/services.mdx": { + "hash": "ce894343645a", + "translated_at": "2026-05-07T10:52:17Z" + }, + "features/browser/integration.mdx": { + "hash": "fdfdb4b62817", + "translated_at": "2026-05-07T10:53:51Z" + }, + "features/clipboard/basics.mdx": { + "hash": "4518bfb618be", + "translated_at": "2026-05-07T10:55:11Z" + }, + "features/dialogs/custom.mdx": { + "hash": "3c4459e7f9be", + "translated_at": "2026-05-07T10:56:52Z" + }, + "features/dialogs/file.mdx": { + "hash": "56f503b264ff", + "translated_at": "2026-05-07T10:58:29Z" + }, + "features/dialogs/message.mdx": { + "hash": "a0dbc0aa205c", + "translated_at": "2026-05-07T10:59:55Z" + }, + "features/dialogs/overview.mdx": { + "hash": "a53f2f2dbf57", + "translated_at": "2026-05-07T11:01:22Z" + }, + "features/drag-and-drop/files.mdx": { + "hash": "93cde3617c0a", + "translated_at": "2026-05-07T11:02:06Z" + }, + "features/drag-and-drop/html.mdx": { + "hash": "29d1b815879f", + "translated_at": "2026-05-07T11:02:53Z" + }, + "features/environment/info.mdx": { + "hash": "879b5e369c35", + "translated_at": "2026-05-07T11:04:48Z" + }, + "features/events/system.mdx": { + "hash": "99933796a4cd", + "translated_at": "2026-05-07T11:06:27Z" + }, + "features/keyboard/shortcuts.mdx": { + "hash": "0707801c419f", + "translated_at": "2026-05-07T11:07:54Z" + }, + "features/menus/application.mdx": { + "hash": "f3012e184058", + "translated_at": "2026-05-07T11:10:06Z" + }, + "features/menus/context.mdx": { + "hash": "0da9502ee8f9", + "translated_at": "2026-05-07T11:12:25Z" + }, + "features/menus/reference.mdx": { + "hash": "50c7083c6804", + "translated_at": "2026-05-07T11:14:06Z" + }, + "features/menus/systray.mdx": { + "hash": "35456a6a7c94", + "translated_at": "2026-05-07T11:16:22Z" + }, + "features/notifications/overview.mdx": { + "hash": "fd054a949c5c", + "translated_at": "2026-05-07T11:17:28Z" + }, + "features/platform/dock.mdx": { + "hash": "5508d0260390", + "translated_at": "2026-05-07T11:18:21Z" + }, + "features/screens/info.mdx": { + "hash": "7c75b63845ac", + "translated_at": "2026-05-07T11:19:51Z" + }, + "features/windows/basics.mdx": { + "hash": "22ab3ac2c722", + "translated_at": "2026-05-07T11:21:36Z" + }, + "features/windows/events.mdx": { + "hash": "68ae278863a2", + "translated_at": "2026-05-07T11:23:21Z" + }, + "features/windows/frameless.mdx": { + "hash": "8250472da67d", + "translated_at": "2026-05-07T11:25:51Z" + }, + "features/windows/multiple.mdx": { + "hash": "67f02d26da23", + "translated_at": "2026-05-07T11:28:04Z" + }, + "features/windows/options.mdx": { + "hash": "a56b6c508b23", + "translated_at": "2026-05-07T11:31:23Z" + }, + "guides/architecture.mdx": { + "hash": "656401718a17", + "translated_at": "2026-05-07T11:31:48Z" + }, + "guides/build/building.mdx": { + "hash": "b307db98ff3b", + "translated_at": "2026-05-07T11:32:10Z" + }, + "guides/build/cross-platform.mdx": { + "hash": "fe856503784b", + "translated_at": "2026-05-07T11:33:23Z" + }, + "guides/build/customization.mdx": { + "hash": "5fdb39dad876", + "translated_at": "2026-05-07T11:34:31Z" + }, + "guides/build/linux.mdx": { + "hash": "afa4feb031ad", + "translated_at": "2026-05-07T11:35:19Z" + }, + "guides/build/macos.mdx": { + "hash": "453cb1df5afe", + "translated_at": "2026-05-07T11:35:47Z" + }, + "guides/build/signing.mdx": { + "hash": "adcc7414ca8e", + "translated_at": "2026-05-07T11:38:53Z" + }, + "guides/build/windows.mdx": { + "hash": "34fb150bd1d1", + "translated_at": "2026-05-07T11:39:13Z" + }, + "guides/cli.mdx": { + "hash": "734e59534ff1", + "translated_at": "2026-05-07T11:41:47Z" + }, + "guides/custom-templates.mdx": { + "hash": "fd0479b54490", + "translated_at": "2026-05-07T11:43:04Z" + }, + "guides/custom-transport.mdx": { + "hash": "1f60cc55f45f", + "translated_at": "2026-05-07T11:43:38Z" + }, + "guides/customising-windows.mdx": { + "hash": "b2c0f84a76db", + "translated_at": "2026-05-07T11:44:02Z" + }, + "guides/distribution/auto-updates.mdx": { + "hash": "e511338ccc89", + "translated_at": "2026-05-07T11:45:57Z" + }, + "guides/distribution/custom-protocols.mdx": { + "hash": "d7e39edb8d62", + "translated_at": "2026-05-07T11:48:13Z" + }, + "guides/e2e-testing.mdx": { + "hash": "409942e28dff", + "translated_at": "2026-05-07T11:48:37Z" + }, + "guides/events-reference.mdx": { + "hash": "e1c103b7e422", + "translated_at": "2026-05-07T11:50:41Z" + }, + "guides/file-associations.mdx": { + "hash": "5756c5fd62ec", + "translated_at": "2026-05-07T11:51:19Z" + }, + "guides/gin-routing.mdx": { + "hash": "4b51d1052334", + "translated_at": "2026-05-07T11:52:11Z" + }, + "guides/gin-services.mdx": { + "hash": "4336b2c6dd73", + "translated_at": "2026-05-07T11:54:19Z" + }, + "guides/installers.mdx": { + "hash": "eb492627c525", + "translated_at": "2026-05-07T11:54:44Z" + }, + "guides/menus.mdx": { + "hash": "c43696cd9e44", + "translated_at": "2026-05-07T11:56:48Z" + }, + "guides/panic-handling.mdx": { + "hash": "cd4e3d40f28d", + "translated_at": "2026-05-07T11:57:19Z" + }, + "guides/performance.mdx": { + "hash": "2cd3efcd296b", + "translated_at": "2026-05-07T11:58:04Z" + }, + "guides/raw-messages.mdx": { + "hash": "974513802fdc", + "translated_at": "2026-05-07T11:59:24Z" + }, + "guides/routing.mdx": { + "hash": "1a9624a10457", + "translated_at": "2026-05-07T11:59:48Z" + }, + "guides/security.mdx": { + "hash": "4b98f155146f", + "translated_at": "2026-05-07T12:00:25Z" + }, + "guides/server-build.mdx": { + "hash": "14b9185722c8", + "translated_at": "2026-05-07T12:01:42Z" + }, + "guides/single-instance.mdx": { + "hash": "c9d6b1edf953", + "translated_at": "2026-05-07T12:02:20Z" + }, + "guides/testing.mdx": { + "hash": "8073196a1496", + "translated_at": "2026-05-07T12:02:46Z" + }, + "guides/windows-uac.mdx": { + "hash": "91140294509d", + "translated_at": "2026-05-07T12:03:20Z" + }, + "migration/v2-to-v3.mdx": { + "hash": "ba7228eb5374", + "translated_at": "2026-05-07T12:05:37Z" + }, + "reference/application.mdx": { + "hash": "6b97eb24f8db", + "translated_at": "2026-05-07T12:06:51Z" + }, + "reference/cli.mdx": { + "hash": "da0cd943a3de", + "translated_at": "2026-05-07T12:06:58Z" + }, + "reference/dialogs.mdx": { + "hash": "4a2534a0eb49", + "translated_at": "2026-05-07T12:09:17Z" + }, + "reference/events.mdx": { + "hash": "34ff503157f7", + "translated_at": "2026-05-07T12:11:59Z" + }, + "reference/frontend-runtime.mdx": { + "hash": "1040ebd9dffd", + "translated_at": "2026-05-07T12:14:22Z" + }, + "reference/menu.mdx": { + "hash": "1ac85e9b0a6d", + "translated_at": "2026-05-07T12:16:21Z" + }, + "reference/overview.mdx": { + "hash": "78b1b9e99288", + "translated_at": "2026-05-07T12:17:11Z" + }, + "reference/updater.mdx": { + "hash": "841cdfe235d9", + "translated_at": "2026-05-07T12:18:30Z" + }, + "reference/window.mdx": { + "hash": "c23046463063", + "translated_at": "2026-05-07T12:20:20Z" + }, + "troubleshooting/mac-syso.mdx": { + "hash": "7aa5d722de2d", + "translated_at": "2026-05-07T12:20:30Z" + }, + "tutorials/01-creating-a-service.mdx": { + "hash": "759d28b3e03b", + "translated_at": "2026-05-07T12:23:20Z" + }, + "tutorials/02-todo-vanilla.mdx": { + "hash": "a50167163c77", + "translated_at": "2026-05-07T12:26:02Z" + }, + "tutorials/03-notes-vanilla.mdx": { + "hash": "7da37d8fbf9c", + "translated_at": "2026-05-07T12:28:23Z" + }, + "tutorials/overview.mdx": { + "hash": "24d96283170f", + "translated_at": "2026-05-07T12:28:45Z" } } \ No newline at end of file diff --git a/docs/src/content/docs/pt/community/links.md b/docs/src/content/docs/pt/community/links.md new file mode 100644 index 00000000000..891ca3b5324 --- /dev/null +++ b/docs/src/content/docs/pt/community/links.md @@ -0,0 +1,28 @@ +--- +title: Links +description: Links e recursos curados pela comunidade para Wails +--- + +Esta página serve como uma lista de links relacionados à comunidade. + +:::tip[Como Enviar um Link] + +Você pode clicar em `Editar página` na parte inferior desta página para enviar um PR. + +::: + +## Awesome Wails + +A [lista definitiva](https://github.com/wailsapp/awesome-wails) de links +relacionados ao Wails. + +## Canais de Suporte + +- [Servidor Discord do Wails](https://discord.gg/bdj28QNHmT) +- [Issues do Github](https://github.com/wailsapp/wails/issues) + +## Redes Sociais + +- [Twitter](https://x.com/wailsapp) +- [Grupo QQ da Comunidade Chinesa do Wails](https://qm.qq.com/cgi-bin/qm/qr?k=PmIURne5hFGNd7QWzW5qd6FV-INEjNJv&jump_from=webapi) - + Número do grupo: 1067173054 \ No newline at end of file diff --git a/docs/src/content/docs/pt/community/templates.md b/docs/src/content/docs/pt/community/templates.md new file mode 100644 index 00000000000..a954c9dc73f --- /dev/null +++ b/docs/src/content/docs/pt/community/templates.md @@ -0,0 +1,131 @@ +--- +title: Modelos +description: Modelos de projeto e kits iniciais para Wails +--- + +:::caution + +Esta página pode estar desatualizada para o Wails v3. + +::: + + + +Esta página serve como uma lista de modelos suportados pela comunidade. Para criar seu próprio +modelo, consulte o guia [Modelos](https://wails.io/docs/guides/templates). + +:::tip[Como Submeter um Modelo] + +Você pode clicar em `Editar esta página` na parte inferior para incluir seus modelos. + +::: + +Para usar estes modelos, execute +`wails init -n "Nome do Seu Projeto" -t [o link abaixo[@version]]` + +Se não houver um sufixo de versão, o modelo de código do branch principal é usado por padrão. +Se houver um sufixo de versão, o modelo de código correspondente à tag desta +versão é usado. + +Exemplo: +`wails init -n "Nome do Seu Projeto" -t https://github.com/misitebao/wails-template-vue` + +:::danger[Atenção] + +**O projeto Wails não mantém, não é responsável nem tem responsabilidade por modelos de terceiros!** + +Se você tiver dúvidas sobre um modelo, inspecione `package.json` e `wails.json` para +ver quais scripts são executados e quais pacotes estão instalados. + +::: + +## Vue + +- [wails-template-vue](https://github.com/misitebao/wails-template-vue) - Modelo Wails + baseado na ecossistema Vue (TypeScript integrado, tema escuro, + internacionalização, roteamento de página única, TailwindCSS) +- [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - + Um modelo 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, Composition API com <script setup>) +- [wails-template-naive](https://github.com/tk103331/wails-template-naive) - + Modelo Wails baseado no Naive UI (Uma biblioteca de componentes Vue 3) +- [wails-template-nuxt](https://github.com/gornius/wails-template-nuxt) - Modelo Wails + usando Nuxt3 limpo e TypeScript com importação automática para o + runtime JS do Wails +- [Wails-Tool-Template](https://github.com/xisuo67/Wails-Tool-Template) - Modelo Wails + usando Vue+TypeScript+Vite+Element-plus (inspirado no NetEase Cloud) + +## Angular + +- [wails-template-angular](https://github.com/mateothegreat/wails-template-angular) - + Angular 15+ repleto de recursos e pronto para produção. +- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - + Angular com TypeScript, Sass, Hot-Reload, Code-Splitting e i18n + +## React + +- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - + Um modelo usando reactjs +- [wails-react-template](https://github.com/flin7/wails-react-template) - Um + modelo minimalista para React que suporta desenvolvimento em tempo real +- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - Um + modelo usando Next.js e TypeScript +- [wails-template-nextjs-app-router](https://github.com/thisisvk-in/wails-template-nextjs-app-router) - + Um modelo usando Next.js e TypeScript com roteador de aplicativo +- [wails-template-nextjs-app-router-src](https://github.com/edai-git/wails-template-nextjs-app-router) - + Um modelo usando Next.js e TypeScript com roteador de aplicativo src + exemplo +- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - + Um modelo para 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) - + Um modelo usando Svelte +- [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - + Um modelo usando Svelte e Vite +- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - + Um modelo usando Svelte e Vite com 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) - + Um modelo usando SvelteKit +- [wails-template-shadcn-svelte](https://github.com/xijaja/wails-template-shadcn-svelte) - + Um modelo usando Sveltekit e Shadcn-Svelte + +## Solid + +- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-ts) - + Um modelo usando Solid + Ts + Vite +- [wails-template-vite-solid-js](https://github.com/xijaja/wails-template-solid-js) - + Um modelo usando Solid + Js + Vite + +## Elm + +- [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - + Desenvolva seu aplicativo GUI com programação funcional e uma configuração de + hot-reload **rápida** :tada: :rocket: +- [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - + Combine os poderes :muscle: de Elm + Tailwind CSS + Wails! Hot reloading + suportado. + +## HTMX + +- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - + Use uma combinação única de htmx puro para interatividade mais templ para + criação de componentes e formulários + +## JavaScript Puro (Vanilla) + +- [wails-pure-js-template](https://github.com/KiddoV/wails-pure-js-template) - Um + modelo com apenas JavaScript básico, HTML e CSS + +## Lit (web components) + +- [wails-lit-shoelace-esbuild-template](https://github.com/Braincompiler/wails-lit-shoelace-esbuild-template) - + Modelo Wails fornecendo ao frontend lit, biblioteca de componentes Shoelace + + prettier e typescript pré-configurados. \ No newline at end of file diff --git a/docs/src/content/docs/pt/concepts/architecture.mdx b/docs/src/content/docs/pt/concepts/architecture.mdx new file mode 100644 index 00000000000..aa01b7d05cc --- /dev/null +++ b/docs/src/content/docs/pt/concepts/architecture.mdx @@ -0,0 +1,328 @@ +--- +title: Como o Wails funciona +description: Entendendo a arquitetura do Wails e como ele alcança desempenho nativo +sidebar: + order: 1 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components"; + +O Wails é um framework para construir aplicativos de desktop usando **Go para o backend** e **tecnologias web para o frontend**. Mas, ao contrário do Electron, o Wails não empacota um navegador; ele usa o **WebView nativo do sistema operacional**. + +```d2 +direction: right + +User: "User" { + shape: person + style.fill: "#3B82F6" +} + +Application: "Your Wails Application" { + Frontend: "Frontend\n(HTML/CSS/JS)" { + shape: rectangle + style.fill: "#8B5CF6" + } + + Runtime: "Wails Runtime" { + Bridge: "Message Bridge" { + shape: diamond + style.fill: "#10B981" + } + + Bindings: "Type-Safe Bindings" { + shape: rectangle + style.fill: "#10B981" + } + } + + Backend: "Go Backend" { + Services: "Your Services" { + shape: rectangle + style.fill: "#00ADD8" + } + + NativeAPIs: "OS APIs" { + shape: rectangle + style.fill: "#00ADD8" + } + } +} + +OS: "Operating System" { + WebView: "Native WebView\n(WebKit/WebView2/WebKitGTK)" { + shape: rectangle + style.fill: "#6B7280" + } + + SystemAPIs: "System APIs\n(Windows/macOS/Linux)" { + shape: rectangle + style.fill: "#6B7280" + } +} + +User -> Application.Frontend: "Interacts with UI" +Application.Frontend <-> Application.Runtime.Bridge: "JSON messages" +Application.Runtime.Bridge <-> Application.Backend.Services: "Direct function calls" +Application.Runtime.Bindings -> Application.Frontend: "TypeScript definitions" +Application.Frontend -> OS.WebView: "Renders in" +Application.Backend.NativeAPIs -> OS.SystemAPIs: "Native calls" +``` + +**Diferenças principais em relação ao Electron:** + +| Aspecto | Wails | Electron | +|--------|-------|----------| +| **Navegador** | WebView fornecido pelo SO | Chromium empacotado (~100MB) | +| **Backend** | Go (compilado) | Node.js (interpretado) | +| **Comunicação** | Bridge em memória | IPC (inter-processos) | +| **Tamanho do pacote** | ~15MB | ~150MB | +| **Memória** | ~10MB | ~100MB+ | +| **Inicialização** | <0,5s | 2-3s | + +## Componentes Principais + +### 1. WebView Nativo + +O Wails usa o mecanismo de renderização web integrado ao sistema operacional: + + + + **WebView2** (Microsoft Edge WebView2) + - Baseado no Chromium (mesmo do navegador Edge) + - Pré-instalado no Windows 10/11 + - Atualizações automáticas via Windows Update + - Suporte completo aos padrões web modernos + + + + **WebKit** (mecanismo de renderização do Safari) + - Integrado ao macOS + - Mesmo motor do navegador Safari + - Excelente desempenho e eficiência energética + - Suporte completo aos padrões web modernos + + + + **WebKitGTK** (porta GTK do WebKit) + - Instalado via gerenciador de pacotes + - Mesmo motor do GNOME Web (Epiphany) + - Bom suporte aos padrões + - Leve e performático + + + +**Por que isso importa:** +- **Sem navegador empacotado** → Tamanho do aplicativo menor +- **Nativo do SO** → Melhor integração e desempenho +- **Atualizações automáticas** → Correções de segurança via atualizações do SO +- **Renderização familiar** → Igual ao navegador do sistema + +### 2. O Bridge do Wails + +O bridge é o coração do Wails; ele permite **comunicação direta** entre Go e JavaScript. + +```d2 +direction: down + +Frontend: "Frontend (JavaScript)" { + shape: rectangle + style.fill: "#8B5CF6" +} + +Bridge: "Wails Bridge" { + Encoder: "JSON Encoder" { + shape: rectangle + } + + Router: "Method Router" { + shape: diamond + style.fill: "#10B981" + } + + Decoder: "JSON Decoder" { + shape: rectangle + } +} + +Backend: "Backend (Go)" { + Services: "Registered Services" { + shape: rectangle + style.fill: "#00ADD8" + } +} + +Frontend -> Bridge.Encoder: "1. Call Go method\nGreet('Alice')" +Bridge.Encoder -> Bridge.Router: "2. Encode to JSON\n{method: 'Greet', args: ['Alice']}" +Bridge.Router -> Backend.Services: "3. Route to service\nGreetService.Greet('Alice')" +Backend.Services -> Bridge.Decoder: "4. Return result\n'Hello, Alice!'" +Bridge.Decoder -> Frontend: "5. Decode to JS\nPromise resolves" +``` + +**Como funciona:** + +1. **Frontend chama um método Go** (via binding auto-gerado) +2. **Bridge codifica a chamada** para JSON (nome do método + argumentos) +3. **Router encontra o método Go** nos serviços registrados +4. **Método Go executa** e retorna um valor +5. **Bridge decodifica o resultado** e envia de volta ao frontend +6. **Promise é resolvida** no JavaScript com o resultado + +**Características de desempenho:** +- **Em memória**: Sem sobrecarga de rede, sem HTTP +- **Zero-copy** quando possível (para grandes volumes de dados) +- **Assíncrono por padrão**: Não bloqueante em ambos os lados +- **Tipado com segurança**: Definições de TypeScript auto-geradas + +### 3. Sistema de Serviços + +Serviços são a maneira recomendada de expor funcionalidade Go ao frontend. + +```go +// Define a service (just a regular Go struct) +type GreetService struct { + prefix string +} + +// Methods with exported names are automatically available +func (g *GreetService) Greet(name string) string { + return g.prefix + name + "!" +} + +func (g *GreetService) GetTime() time.Time { + return time.Now() +} + +// Register the service +app := application.New(application.Options{ + Services: []application.Service{ + application.NewService(&GreetService{prefix: "Hello, "}), + }, +}) +``` + +**Descoberta de serviços:** +- O Wails **varre sua struct** na inicialização +- **Métodos exportados** tornam-se chamáveis do frontend +- **Informações de tipo** são extraídas para bindings de TypeScript +- **Tratamento de erros** é automático (erros Go → exceções JS) + +**Binding de TypeScript gerado:** +```typescript +// Auto-generated in frontend/bindings/GreetService.ts +export function Greet(name: string): Promise +export function GetTime(): Promise +``` + +**Por que serviços?** +- **Tipado com segurança**: Suporte completo ao TypeScript +- **Descoberta automática**: Sem registro manual de métodos +- **Organizado**: Agrupe funcionalidades relacionadas +- **Testável**: Serviços são apenas structs Go + +[Mais informações sobre serviços →](/pt/features/bindings/services) + +### 4. Sistema de Eventos + +Eventos permitem **comunicação pub/sub** entre componentes. + +```d2 +direction: right + +GoService: "Go Service" { + shape: rectangle + style.fill: "#00ADD8" +} + +EventBus: "Event Bus" { + shape: cylinder + style.fill: "#10B981" +} + +Frontend1: "Window 1" { + shape: rectangle + style.fill: "#8B5CF6" +} + +Frontend2: "Window 2" { + shape: rectangle + style.fill: "#8B5CF6" +} + +GoService -> EventBus: "Emit('data-updated', data)" +EventBus -> Frontend1: "Notify subscribers" +EventBus -> Frontend2: "Notify subscribers" +Frontend1 -> EventBus: "On('data-updated', handler)" +Frontend2 -> EventBus: "On('data-updated', handler)" +``` + +**Casos de uso:** +- **Comunicação entre janelas**: Uma janela notifica as outras +- **Tarefas em segundo plano**: Serviço Go notifica a UI sobre o progresso +- **Sincronização de estado**: Mantém múltiplas janelas sincronizadas +- **Acoplamento fraco**: Componentes não precisam de referências diretas + +**Exemplo:** +```go +// Go: Emit an event +app.Event.Emit("user-logged-in", user) +``` + +```javascript +// JavaScript: Listen for event +import { Events } from '@wailsio/runtime' + +Events.On('user-logged-in', (user) => { + console.log('User logged in:', user) +}) +``` + +[Mais informações sobre eventos →](/pt/features/events/system) + +## Ciclo de Vida do Aplicativo + +Entender o ciclo de vida ajuda você a saber quando inicializar recursos e fazer limpeza. + +```d2 +direction: down + +Start: "Application Start" { + shape: oval + style.fill: "#10B981" +} + +Init: "Initialisation" { + Create: "Create Application" { + shape: rectangle + } + + Register: "Register Services" { + shape: rectangle + } + + Setup: "Setup Windows/Menus" { + shape: rectangle + } +} + +Run: "Event Loop" { + Events: "Process Events" { + shape: rectangle + } + + Messages: "Handle Messages" { + shape: rectangle + } + + Render: "Update UI" { + shape: rectangle + } +} + +Shutdown: "Shutdown" { + Cleanup: "Cleanup Resources" { + shape: rectangle + } + + Save: "Save State" {--- + +**Dúvidas sobre a arquitetura?** Pergunte no [Discord](https://discord.gg/JDdSxwjhGf) ou consulte a [referência da API](/pt/reference/overview). \ No newline at end of file diff --git a/docs/src/content/docs/pt/concepts/bridge.mdx b/docs/src/content/docs/pt/concepts/bridge.mdx new file mode 100644 index 00000000000..513be047f0a --- /dev/null +++ b/docs/src/content/docs/pt/concepts/bridge.mdx @@ -0,0 +1,391 @@ +--- +title: Ponte Go-Frontend +description: Mergulho profundo em como o Wails permite comunicação direta entre Go e JavaScript +sidebar: + order: 3 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components"; + +## Comunicação Direta Go-JavaScript + +O Wails fornece uma **ponte direta em memória** entre Go e JavaScript, permitindo comunicação perfeita sem sobrecarga de HTTP, limites de processo ou gargalos de serialização. + +## Visão Geral + +```d2 +direction: right + +Frontend: "Frontend (JavaScript)" { + UI: "React/Vue/Vanilla" { + shape: rectangle + style.fill: "#8B5CF6" + } + + Bindings: "Auto-Generated Bindings" { + shape: rectangle + style.fill: "#A78BFA" + } +} + +Bridge: "Wails Bridge" { + Encoder: "JSON Encoder" { + shape: rectangle + style.fill: "#10B981" + } + + Router: "Method Router" { + shape: diamond + style.fill: "#10B981" + } + + Decoder: "JSON Decoder" { + shape: rectangle + style.fill: "#10B981" + } + + TypeGen: "Type Generator" { + shape: rectangle + style.fill: "#10B981" + } +} + +Backend: "Backend (Go)" { + Services: "Your Services" { + shape: rectangle + style.fill: "#00ADD8" + } + + Registry: "Service Registry" { + shape: rectangle + style.fill: "#00ADD8" + } +} + +Frontend.UI -> Frontend.Bindings: "import { Method }" +Frontend.Bindings -> Bridge.Encoder: "Call Method('arg')" +Bridge.Encoder -> Bridge.Router: "Encode to JSON" +Bridge.Router -> Backend.Registry: "Find service" +Backend.Registry -> Backend.Services: "Invoke method" +Backend.Services -> Bridge.Decoder: "Return result" +Bridge.Decoder -> Frontend.Bindings: "Decode to JS" +Frontend.Bindings -> Frontend.UI: "Promise resolves" +Bridge.TypeGen -> Frontend.Bindings: "Generate types" +``` + +**Insight principal:** Sem HTTP, sem IPC, sem limites de processo. Apenas **chamadas de função diretas** com **segurança de tipos**. + +## Como Funciona: Passo a Passo + +### 1. Registro de Serviço (Inicialização) + +Quando sua aplicação inicia, o Wails escaneia seus serviços: + +```go +type GreetService struct { + prefix string +} + +func (g *GreetService) Greet(name string) string { + return g.prefix + name + "!" +} + +func (g *GreetService) Add(a, b int) int { + return a + b +} + +// Register service +app := application.New(application.Options{ + Services: []application.Service{ + application.NewService(&GreetService{prefix: "Hello, "}), + }, +}) +``` + +**O que o Wails faz:** +1. **Escaneia a estrutura** em busca de métodos exportados +2. **Extrai informações de tipo** (parâmetros, tipos de retorno) +3. **Constrói um registro** mapeando nomes de métodos para funções +4. **Gera bindings de TypeScript** com definições de tipo completas + +### 2. Geração de Bindings (Tempo de Compilação) + +O Wails gera bindings de TypeScript automaticamente: + +```typescript +// Auto-generated: frontend/bindings/GreetService.ts +export function Greet(name: string): Promise +export function Add(a: number, b: number): Promise +``` + +**Mapeamento de tipos:** + +| Tipo Go | Tipo TypeScript | +|---------|-----------------| +| `string` | `string` | +| `int`, `int32`, `int64` | `number` | +| `float32`, `float64` | `number` | +| `bool` | `boolean` | +| `[]T` | `T[]` | +| `map[string]T` | `Record` | +| `struct` | `interface` | +| `time.Time` | `Date` | +| `error` | Exceção (lançada) | + +### 3. Chamada no Frontend (Tempo de Execução) + +O desenvolvedor chama o método Go do JavaScript: + +```javascript +import { Greet, Add } from './bindings/GreetService' + +// Call Go from JavaScript +const greeting = await Greet("World") +console.log(greeting) // "Hello, World!" + +const sum = await Add(5, 3) +console.log(sum) // 8 +``` + +**O que acontece:** +1. **Função de binding chamada** - `Greet("World")` +2. **Mensagem criada** - `{ service: "GreetService", method: "Greet", args: ["World"] }` +3. **Enviada para a ponte** - Via ponte JavaScript do WebView +4. **Promise retornada** - Aguarda resposta + +### 4. Processamento da Ponte (Tempo de Execução) + +A ponte recebe a mensagem e a processa: + +```d2 +direction: down + +Receive: "Receive Message" { + shape: rectangle + style.fill: "#10B981" +} + +Parse: "Parse JSON" { + shape: rectangle +} + +Validate: "Validate" { + Check: "Service exists?" { + shape: diamond + } + + CheckMethod: "Method exists?" { + shape: diamond + } + + CheckTypes: "Types correct?" { + shape: diamond + } +} + +Invoke: "Invoke Go Method" { + shape: rectangle + style.fill: "#00ADD8" +} + +Encode: "Encode Result" { + shape: rectangle +} + +Send: "Send Response" { + shape: rectangle + style.fill: "#10B981" +} + +Error: "Send Error" { + shape: rectangle + style.fill: "#EF4444" +} + +Receive -> Parse +Parse -> Validate.Check +Validate.Check -> Validate.CheckMethod: "Yes" +Validate.Check -> Error: "No" +Validate.CheckMethod -> Validate.CheckTypes: "Yes" +Validate.CheckMethod -> Error: "No" +Validate.CheckTypes -> Invoke: "Yes" +Validate.CheckTypes -> Error: "No" +Invoke -> Encode: "Success" +Invoke -> Error: "Error" +Encode -> Send +``` + +**Segurança:** Apenas serviços registrados e métodos exportados são chamáveis. + +### 5. Execução Go (Tempo de Execução) + +O método Go é executado: + +```go +func (g *GreetService) Greet(name string) string { + // This runs in Go + return g.prefix + name + "!" +} +``` + +**Contexto de execução:** +- Executa em uma **goroutine** (não bloqueante) +- Tem acesso a **todos os recursos do Go** (sistema de arquivos, rede, bancos de dados) +- Pode chamar **outro código Go** livremente +- Retorna resultado ou erro + +### 6. Resposta (Tempo de Execução) + +O resultado é enviado de volta ao JavaScript: + +```javascript +// Promise resolves with result +const greeting = await Greet("World") +// greeting = "Hello, World!" +``` + +**Tratamento de erros:** + +```go +func (g *GreetService) Divide(a, b float64) (float64, error) { + if b == 0 { + return 0, errors.New("division by zero") + } + return a / b, nil +} +``` + +```javascript +try { + const result = await Divide(10, 0) +} catch (error) { + console.error("Go error:", error) // "division by zero" +} +``` + +## Características de Desempenho + +### Velocidade + +**Sobrecarga típica de chamada:** <1ms + +``` +Frontend Call → Bridge → Go Execution → Bridge → Frontend Response + ↓ ↓ ↓ ↓ ↓ + <0.1ms <0.1ms [varies] <0.1ms <0.1ms +``` + +**Comparado a alternativas:** +- **HTTP/REST:** 5-50ms (stack de rede, serialização) +- **IPC:** 1-10ms (limites de processo, marshalling) +- **Wails Bridge:** <1ms (em memória, chamada direta) + +### Memória + +**Sobrecarga por chamada:** ~1KB (buffer de mensagem) + +**Otimização zero-copy:** Dados grandes (>1MB) usam memória compartilhada quando possível. + +### Concorrência + +**Chamadas são concorrentes:** +- Cada chamada executa em sua própria goroutine +- Múltiplas chamadas podem executar simultaneamente +- Sem bloqueio entre chamadas + +```javascript +// These run concurrently +const [result1, result2, result3] = await Promise.all([ + SlowOperation1(), + SlowOperation2(), + SlowOperation3(), +]) +``` + +## Sistema de Tipos + +### Tipos Suportados + +#### Primitivos + +```go +// Go +func Example( + s string, + i int, + f float64, + b bool, +) (string, int, float64, bool) { + return s, i, f, b +} +``` + +```typescript +// TypeScript (auto-generated) +function Example( + s: string, + i: number, + f: number, + b: boolean, +): Promise<[string, number, number, boolean]> +``` + +#### Fatias e Arrays + +```go +// Go +func Sum(numbers []int) int { + total := 0 + for _, n := range numbers { + total += n + } + return total +} +``` + +```typescript +// TypeScript +function Sum(numbers: number[]): Promise + +// Usage +const total = await Sum([1, 2, 3, 4, 5]) // 15 +``` + +#### Mapas + +```go +// Go +func GetConfig() map[string]interface{} { + return map[string]interface{}{ + "theme": "dark", + "fontSize": 14, + "enabled": true, + } +} +``` + +```typescript +// TypeScript +function GetConfig(): Promise> + +// Usage +const config = await GetConfig() +console.log(config.theme) // "dark" +``` + +#### Estruturas + +```go +// Go +type User struct { + ID int `json:"id"` + Name string `json:"name"` + Email string `json:"email"` +} + +func GetUser(id int) (*User, error) { + return &User{ + ID: id, + Name: "Alice",--- + +**Dúvidas sobre a ponte?** Pergunte no [Discord](https://discord.gg/JDdSxwjhGf) ou verifique os [exemplos de binding](https://github.com/wailsapp/wails/tree/master/v3/examples/binding). \ No newline at end of file diff --git a/docs/src/content/docs/pt/concepts/build-system.mdx b/docs/src/content/docs/pt/concepts/build-system.mdx new file mode 100644 index 00000000000..65ab93b7be9 --- /dev/null +++ b/docs/src/content/docs/pt/concepts/build-system.mdx @@ -0,0 +1,424 @@ +--- +title: Sistema de Build +description: Entenda como o Wails compila e empacota seu aplicativo +sidebar: + order: 4 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components"; + +## Sistema de Build Unificado + +O Wails oferece um **sistema de build unificado** que compila código Go, empaceta ativos do frontend, embute tudo em um único executável e lida com builds específicos de plataforma — tudo com um único comando. + +```bash +wails3 build +``` + +**Saída:** Executável nativo com tudo embutido. + +## Visão Geral do Processo de Build + +{/* +TODO: Corrigir a geração do diagrama D2 ou incorporar como imagem. +O bloco de código D2 anterior estava causando erros de análise MDX no pipeline de build. +*/} + +**[Espaço Reservado para Diagrama do Processo de Build]** + + +## Fases do Build + +### 1. Fase de Análise + +O Wails analisa seu código Go para entender seus serviços: + +```go +type GreetService struct { + prefix string +} + +func (g *GreetService) Greet(name string) string { + return g.prefix + name + "!" +} +``` + +**O que o Wails extrai:** +- Nome do serviço: `GreetService` +- Nome do método: `Greet` +- Tipos de parâmetro: `string` +- Tipos de retorno: `string` + +**Usado para:** Gerar bindings de TypeScript + +### 2. Fase de Geração + +#### Bindings de TypeScript + +O Wails gera bindings com tipagem segura: + +```typescript +// Auto-generated: frontend/bindings/GreetService.ts +export function Greet(name: string): Promise { + return window.wails.Call('GreetService.Greet', name) +} +``` + +**Benefícios:** +- Segurança de tipos completa +- Autocompletar na IDE +- Erros em tempo de compilação +- Comentários JSDoc + +#### Build do Frontend + +Seu bundler de frontend é executado (Vite, webpack, etc.): + +```bash +# Exemplo com Vite +vite build --outDir dist +``` + +**O que acontece:** +- JavaScript/TypeScript compilado +- CSS processado e minificado +- Otimização de ativos +- Mapas de origem gerados (apenas dev) +- Saída para `frontend/dist/` + +### 3. Fase de Compilação + +#### Compilação Go + +O código Go é compilado com otimizações: + +```bash +go build -ldflags="-s -w" -o myapp.exe +``` + +**Flags:** +- `-s`: Remove a tabela de símbolos +- `-w`: Remove informações de depuração DWARF +- Resultado: Binário menor (~30% de redução) + +**Específico da plataforma:** +- Windows: `.exe` com ícone embutido +- macOS: Estrutura de bundle `.app` +- Linux: Binário ELF + +#### Embutimento de Ativos + +Os ativos do frontend são embutidos no binário Go: + +```go +//go:embed frontend/dist +var assets embed.FS +``` + +**Resultado:** Um único executável com tudo dentro. + +### 4. Saída + +**Um único binário nativo:** +- Windows: `myapp.exe` (~15MB) +- macOS: `myapp.app` (~15MB) +- Linux: `myapp` (~15MB) + +**Sem dependências** (exceto o WebView do sistema). + +## Desenvolvimento vs Produção + + + + **Otimizado para velocidade:** + + ```bash + wails3 dev + ``` + + **O que acontece:** + 1. Inicia o servidor de desenvolvimento do frontend (Vite na porta 5173) + 2. Compila o Go sem otimizações + 3. Inicia o aplicativo apontando para o servidor de desenvolvimento + 4. Habilita hot reload + 5. Inclui mapas de origem + + **Características:** + - **Recompilações rápidas** (<1s para alterações no frontend) + - **Sem embutimento de ativos** (servidos pelo servidor de dev) + - **Símbolos de depuração** incluídos + - **Mapas de origem** habilitados + - **Logs verbosos** + + **Tamanho do arquivo:** Maior (~50MB com símbolos de depuração) + + + + **Otimizado para tamanho e desempenho:** + + ```bash + wails3 build + ``` + + **O que acontece:** + 1. Compila o frontend para produção (minificado) + 2. Compila o Go com otimizações + 3. Remove símbolos de depuração + 4. Embute os ativos + 5. Cria um único binário + + **Características:** + - **Código otimizado** (minificado, tree-shaken) + - **Ativos embutidos** (sem arquivos externos) + - **Símbolos de depuração removidos** + - **Sem mapas de origem** + - **Logs mínimos** + + **Tamanho do arquivo:** Menor (~15MB) + + + +## Comandos de Build + +### Build Básico + +```bash +wails3 build +``` + +**Saída:** `build/bin/myapp[.exe]` + +### Build para Plataforma Específica + +```bash +# Build para Windows (de qualquer OS) +wails3 build -platform windows/amd64 + +# Build para macOS +wails3 build -platform darwin/amd64 +wails3 build -platform darwin/arm64 + +# Build para Linux +wails3 build -platform linux/amd64 +``` + +**Compilação cruzada:** Compile para qualquer plataforma a partir de qualquer plataforma. + +### Build com Opções + +```bash +# Diretório de saída personalizado +wails3 build -o ./dist/myapp + +# Pular build do frontend (usar existente) +wails3 build -skipbindings + +# Build limpo (remover cache) +wails3 build -clean + +# Saída verbosa +wails3 build -v +``` + +### Modos de Build + +```bash +# Build de depuração (inclui símbolos) +wails3 build -debug + +# Build de produção (padrão, otimizado) +wails3 build + +# Build de desenvolvimento (rápido, não otimizado) +wails3 build -devbuild +``` + +## Configuração de Build + +### Taskfile.yml + +O Wails usa [Taskfile](https://taskfile.dev/) para configuração de build: + +```yaml +# Taskfile.yml +version: '3' + +tasks: + build: + desc: Build the application + cmds: + - wails3 build + + build:windows: + desc: Build for Windows + cmds: + - wails3 build -platform windows/amd64 + + build:macos: + desc: Build for macOS (Universal) + cmds: + - wails3 build -platform darwin/amd64 + - wails3 build -platform darwin/arm64 + - lipo -create -output build/bin/myapp.app build/bin/myapp-amd64.app build/bin/myapp-arm64.app + + build:linux: + desc: Build for Linux + cmds: + - wails3 build -platform linux/amd64 +``` + +**Executar tarefas:** + +```bash +task build:windows +task build:macos +task build:linux +``` + +### Arquivo de Opções de Build + +Crie `build/build.json` para configuração persistente: + +```json +{ + "name": "My Application", + "version": "1.0.0", + "author": "Your Name", + "description": "Application description", + "icon": "build/appicon.png", + "outputFilename": "myapp", + "platforms": ["windows/amd64", "darwin/amd64", "linux/amd64"], + "frontend": { + "dir": "./frontend", + "install": "npm install", + "build": "npm run build", + "dev": "npm run dev" + }, + "go": { + "ldflags": "-s -w -X main.version={{.Version}}" + } +} +``` + +## Embutimento de Ativos + +### Como Funciona + +O Wails usa o pacote `embed` do Go: + +```go +package main + +import ( + "embed" + "github.com/wailsapp/wails/v3/pkg/application" +) + +//go:embed frontend/dist +var assets embed.FS + +func main() { + app := application.New(application.Options{ + Name: "My App", + Assets: application.AssetOptions{ + Handler: application.AssetFileServerFS(assets), + }, + }) + + app.Window.New() + app.Run() +} +``` + +**No momento do build:** +1. Frontend construído em `frontend/dist/` +2. Diretiva `//go:embed` inclui os arquivos +3. Arquivos compilados no binário +4. Binário contém tudo + +**Em tempo de execução:** +1. App inicia +2. Ativos servidos da memória +3. Sem E/S de disco para ativos +4. Carregamento rápido + +### Ativos Personalizados + +Incorpore arquivos adicionais: + +```go +//go:embed frontend/dist +var frontendAssets embed.FS + +//go:embed data/*.json +var dataAssets embed.FS + +//go:embed templates/*.html +var templateAssets embed.FS +``` + +## Otimizações de Build + +### Otimizações de Frontend + +**Vite (padrão):** + +```javascript +// vite.config.js +export default { + build: { + minify: 'terser', + terserOptions: { + compress: { + drop_console: true, // Remove console.log + drop_debugger: true, + }, + }, + rollupOptions: { + output: { + manualChunks: { + vendor: ['react', 'react-dom'], // Separa bundle de vendor + }, + }, + }, + }, +} +``` + +**Resultados:** +- JavaScript minificado (~70% de redução) +- CSS minificado (~60% de redução) +- Imagens otimizadas +- Tree-shaking aplicado + +### Otimizações Go + +**Flags do compilador:** + +```bash +-ldflags="-s -w" +``` + +- `-s`: Remove tabela de símbolos (~10% de redução) +- `-w`: Remove informações de depuração DWARF (~20% de redução) + +**Otimizações adicionais:** + +```bash +-ldflags="-s -w -X main.version=1.0.0" +``` + +- `-X`: Define valores de variáveis em tempo de build +- Útil para números de versão, datas de build + +### Compressão de Binário + +**UPX (opcional):** + +```bash +# Após o build +upx --best build/bin/myapp.exe +``` + +**Resultados:** +- ~50% de redução de tamanho**Dúvidas sobre builds?** Pergunte no [Discord](https://discord.gg/JDdSxwjhGf) ou verifique os [exemplos de build](https://github.com/wailsapp/wails/tree/master/v3/examples/build). \ No newline at end of file diff --git a/docs/src/content/docs/pt/concepts/lifecycle.mdx b/docs/src/content/docs/pt/concepts/lifecycle.mdx new file mode 100644 index 00000000000..a7490e1b377 --- /dev/null +++ b/docs/src/content/docs/pt/concepts/lifecycle.mdx @@ -0,0 +1,368 @@ +--- +title: Ciclo de Vida da Aplicação +description: Compreendendo o ciclo de vida da aplicação Wails, desde a inicialização até o encerramento +sidebar: + order: 2 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components"; + +## Compreendendo o Ciclo de Vida da Aplicação + +Aplicações de desktop possuem um ciclo de vida que vai da inicialização ao encerramento. O Wails v3 fornece **serviços**, **eventos** e **hooks** para gerenciar esse ciclo de forma eficaz. + +## As Etapas do Ciclo de Vida + +```d2 +direction: down + +Start: "Application Start" { + shape: oval + style.fill: "#10B981" +} + +Init: "Initialisation" { + Parse: "Parse Options" { + shape: rectangle + } + Register: "Register Services" { + shape: rectangle + } + Setup: "Setup Runtime" { + shape: rectangle + } +} + +AppRun: "app.Run()" { + shape: rectangle + style.fill: "#3B82F6" +} + +ServiceStartup: "Service Startup" { + shape: rectangle + style.fill: "#8B5CF6" +} + +EventLoop: "Event Loop" { + Process: "Process Events" { + shape: rectangle + } + Handle: "Handle Messages" { + shape: rectangle + } + Update: "Update UI" { + shape: rectangle + } +} + +QuitSignal: "Quit Signal" { + shape: diamond + style.fill: "#F59E0B" +} + +ShouldQuit: "ShouldQuit Check" { + shape: rectangle + style.fill: "#3B82F6" +} + +OnShutdown: "OnShutdown Callbacks" { + shape: rectangle + style.fill: "#3B82F6" +} + +ServiceShutdown: "Service Shutdown" { + shape: rectangle + style.fill: "#8B5CF6" +} + +Cleanup: "Cleanup" { + Close: "Close Windows" { + shape: rectangle + } + Release: "Release Resources" { + shape: rectangle + } +} + +End: "Application End" { + shape: oval + style.fill: "#EF4444" +} + +Start -> Init.Parse +Init.Parse -> Init.Register +Init.Register -> Init.Setup +Init.Setup -> AppRun +AppRun -> ServiceStartup +ServiceStartup -> EventLoop.Process +EventLoop.Process -> EventLoop.Handle +EventLoop.Handle -> EventLoop.Update +EventLoop.Update -> EventLoop.Process: "Loop" +EventLoop.Process -> QuitSignal: "User quits" +QuitSignal -> ShouldQuit: "Check allowed?" +ShouldQuit -> EventLoop.Process: "Denied" +ShouldQuit -> OnShutdown: "Allowed" +OnShutdown -> ServiceShutdown +ServiceShutdown -> Cleanup.Close +Cleanup.Close -> Cleanup.Release +Cleanup.Release -> End +``` + +### 1. Criação da Aplicação + +Crie sua aplicação com `application.New()`: + +```go +app := application.New(application.Options{ + Name: "My App", + Description: "An application built with Wails", + Services: []application.Service{ + application.NewService(&MyService{}), + }, + Assets: application.AssetOptions{ + Handler: application.BundledAssetFileServer(assets), + }, +}) +``` + +**O que acontece:** +1. As opções são analisadas e validadas +2. Os serviços são registrados (mas ainda não iniciados) +3. O servidor de ativos é configurado +4. O runtime é configurado + +### 2. Executando a Aplicação + +Chame `app.Run()` para iniciar a aplicação: + +```go +err := app.Run() // Blocks until quit +if err != nil { + log.Fatal(err) +} +``` + +**O que acontece:** +1. Os serviços são iniciados na ordem de registro +2. Os ouvintes de eventos são ativados +3. As janelas podem ser criadas +4. O loop de eventos começa + +### 3. Loop de Eventos + +A aplicação entra no loop de eventos, onde passa a maior parte do seu tempo: + +- Eventos do SO são processados (mouse, teclado, eventos de janela) +- Mensagens de Go para JS são tratadas +- Chamadas de JS para Go são executadas +- Atualizações de UI são renderizadas + +### 4. Encerramento + +Quando a aplicação encerra: + +1. O callback `ShouldQuit` é verificado (se definido) +2. Os callbacks `OnShutdown` são executados +3. Os serviços são encerrados na ordem inversa de registro +4. As janelas são fechadas +5. Os recursos são liberados + +## Ciclo de Vida dos Serviços + +Os serviços são a maneira principal de gerenciar o ciclo de vida no Wails v3. Eles fornecem hooks de inicialização e encerramento por meio de interfaces. Para documentação completa sobre serviços, consulte o [Guia de Serviços](/pt/features/bindings/services). + +### Criando um Serviço + +```go +type MyService struct { + db *sql.DB +} + +// ServiceStartup is called when the application starts +func (s *MyService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { + var err error + s.db, err = sql.Open("sqlite3", "app.db") + if err != nil { + return err // Startup aborts if error returned + } + + // Run migrations + if err := s.runMigrations(); err != nil { + return err + } + + return nil +} + +// ServiceShutdown is called when the application shuts down +func (s *MyService) ServiceShutdown() error { + if s.db != nil { + return s.db.Close() + } + return nil +} +``` + +### Registrando Serviços + +```go +app := application.New(application.Options{ + Services: []application.Service{ + application.NewService(&MyService{}), + application.NewService(&AnotherService{}), + }, +}) +``` + +**Pontos-chave:** +- Os serviços são iniciados na ordem de registro +- Os serviços são encerrados na ordem **inversa** de registro +- Se o `ServiceStartup` de um serviço retornar um erro, a aplicação é abortada +- O `ctx` passado para `ServiceStartup` é cancelado quando o encerramento começa + +### Usando o Contexto da Aplicação + +O contexto passado para `ServiceStartup` é válido durante toda a vida da aplicação: + +```go +func (s *MyService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { + // Start a background task that respects shutdown + go func() { + ticker := time.NewTicker(5 * time.Minute) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + s.performBackgroundSync() + case <-ctx.Done(): + // Application is shutting down + return + } + } + }() + + return nil +} +``` + +Você também pode acessar o contexto a partir da instância da aplicação: + +```go +app := application.Get() +ctx := app.Context() +``` + +## Hooks de Nível da Aplicação + +Estes são callbacks de conveniência em `application.Options` que permitem integrar-se ao ciclo de vida da aplicação sem criar um serviço completo. Eles são úteis para tarefas simples de limpeza, confirmação de encerramento ou quando você precisa executar código em pontos específicos da sequência de encerramento. + +Para um gerenciamento de ciclo de vida mais complexo com lógica de inicialização, injeção de dependência ou recursos com estado, use [Serviços](#services-lifecycle) em vez disso. + +### ShouldQuit + +O callback `ShouldQuit` é chamado sempre que um encerramento é solicitado — seja pelo usuário fechando a última janela, pressionando Cmd+Q (macOS) / Alt+F4 (Windows) ou chamando `app.Quit()` programaticamente. + +**Valor de retorno:** +- Retorne `true` para permitir que o encerramento prossiga (a aplicação será encerrada) +- Retorne `false` para cancelar o encerramento (a aplicação continua em execução) + +Esta é sua oportunidade de interceptar solicitações de encerramento e, opcionalmente, impedi-las, por exemplo, para solicitar ao usuário sobre alterações não salvas: + +```go +app := application.New(application.Options{ + ShouldQuit: func() bool { + if !hasUnsavedChanges() { + return true // No unsaved changes, allow quit + } + + // Prompt the user + result, _ := application.QuestionDialog(). + SetTitle("Unsaved Changes"). + SetMessage("You have unsaved changes. Quit anyway?"). + AddButton("Quit", "quit"). + AddButton("Cancel", "cancel"). + Show() + + // Only quit if user clicked "Quit" + return result == "quit" + }, +}) +``` + +Se `ShouldQuit` não estiver definido, a aplicação será encerrada imediatamente quando solicitada. + +**Quando ShouldQuit é chamado:** +- O usuário fecha a última janela (a menos que `DisableQuitOnLastWindowClosed` esteja definido) +- O usuário pressiona Cmd+Q no macOS +- O usuário pressiona Alt+F4 no Windows (quando focado na última janela) +- O código chama `app.Quit()` + +**Quando ShouldQuit NÃO é chamado:** +- O processo é encerrado forçadamente (SIGKILL, Gerenciador de Tarefas forçar encerramento) +- `os.Exit()` é chamado diretamente + +### OnShutdown + +O callback `OnShutdown` é chamado quando a aplicação é confirmada para estar encerrando (após `ShouldQuit` retornar `true`, se definido). Use isso para tarefas de limpeza, como salvar o estado, fechar conexões de banco de dados ou liberar recursos. + +```go +app := application.New(application.Options{ + OnShutdown: func() { + // Save application state + saveState() + + // Close connections----------|--------------------------------| +| macOS | O app continua em execução (a barra de menu permanece) | +| Windows | O app encerra | +| Linux | O app encerra | + +O macOS segue as convenções nativas da plataforma, onde as aplicações geralmente permanecem ativas na barra de menu mesmo sem janelas abertas. Windows e Linux encerram por padrão. + +**Fazer todas as plataformas encerrarem quando a última janela for fechada:** + +```go +app := application.New(application.Options{ + Mac: application.MacOptions{ + ApplicationShouldTerminateAfterLastWindowClosed: true, + }, +}) +``` + +**Fazer todas as plataformas permanecerem em execução quando a última janela for fechada:** + +Isso é útil para aplicações de bandeja do sistema ou apps que devem permanecer em execução em segundo plano. + +```go +app := application.New(application.Options{ + Windows: application.WindowsOptions{ + DisableQuitOnLastWindowClosed: true, + }, + Linux: application.LinuxOptions{ + DisableQuitOnLastWindowClosed: true, + }, +}) +``` + +## Padrões Comuns + +### Padrão 1: Serviço de Banco de Dados + +```go +type DatabaseService struct { + db *sql.DB +} + +func (s *DatabaseService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { + var err error + s.db, err = sql.Open("sqlite3", "app.db") + if err != nil { + return fmt.Errorf("falha ao abrir banco de dados: %w", err) + } + + if err := s.db.PingContext(ctx); err != nil { + return fmt.Errorf("falha ao conectar ao banco de dados: %w", err) + } + + return nil +}**Dúvidas sobre o ciclo de vida?** Pergunte no [Discord](https://discord.gg/JDdSxwjhGf) ou verifique os [exemplos](https://github.com/wailsapp/wails/tree/master/v3/examples). \ No newline at end of file diff --git a/docs/src/content/docs/pt/concepts/manager-api.mdx b/docs/src/content/docs/pt/concepts/manager-api.mdx new file mode 100644 index 00000000000..9b9272f339f --- /dev/null +++ b/docs/src/content/docs/pt/concepts/manager-api.mdx @@ -0,0 +1,266 @@ +--- +title: API do Gerenciador +description: Estrutura de API organizada com interfaces de gerenciador focadas +sidebar: + order: 2 +--- + +import { Tabs, TabItem } from "@astrojs/starlight/components"; + +A API do Gerenciador do Wails v3 oferece uma maneira organizada e descoberta de acessar a funcionalidade do aplicativo por meio de structs de gerenciador focados. Esta nova estrutura de API agrupa métodos relacionados, mantendo total compatibilidade com a API tradicional do App. + +## Visão geral + +A API do Gerenciador organiza a funcionalidade do aplicativo em onze áreas focadas: + +- **`app.Window`** - Criação, gerenciamento e callbacks de janelas +- **`app.ContextMenu`** - Registro e gerenciamento de menus de contexto +- **`app.KeyBinding`** - Gerenciamento global de atalhos de teclado +- **`app.Browser`** - Integração com navegador (abertura de URLs e arquivos) +- **`app.Env`** - Informações de ambiente e estado do sistema +- **`app.Dialog`** - Operações de diálogo de arquivos e mensagens +- **`app.Event`** - Manipulação de eventos personalizados e eventos do aplicativo +- **`app.Menu`** - Gerenciamento do menu do aplicativo +- **`app.Screen`** - Gerenciamento de telas e transformações de coordenadas +- **`app.Clipboard`** - Operações de texto na área de transferência +- **`app.SystemTray`** - Criação e gerenciamento de ícones na bandeja do sistema + +## Benefícios + +- **Melhor descoberta** - O preenchimento automático do IDE mostra a superfície da API organizada +- **Organização de código aprimorada** - Métodos relacionados agrupados juntos +- **Manutenção aprimorada** - Separação de responsabilidades entre os gerenciadores +- **Extensibilidade futura** - Mais fácil adicionar novos recursos a áreas específicas + +## Uso + +A API do Gerenciador fornece acesso organizado a toda a funcionalidade do aplicativo: + +```go +// Eventos e manipulação de eventos personalizados +app.Event.Emit("custom", data) +app.Event.On("custom", func(e *CustomEvent) { ... }) + +// Gerenciamento de janelas +window, _ := app.Window.GetByName("main") +app.Window.OnCreate(func(window Window) { ... }) + +// Integração com navegador +app.Browser.OpenURL("https://wails.io") + +// Gerenciamento de menus +menu := app.Menu.New() +app.Menu.Set(menu) + +// Bandeja do sistema +systray := app.SystemTray.New() +``` + +## Referência do Gerenciador + +### Gerenciador de Janelas + +Gerencia a criação, recuperação e callbacks de ciclo de vida de janelas. + +```go +// Criar janelas +window := app.Window.New() +window := app.Window.NewWithOptions(options) +current := app.Window.Current() + +// Encontrar janelas +window, exists := app.Window.GetByName("main") +windows := app.Window.GetAll() + +// Callbacks de janela +app.Window.OnCreate(func(window Window) { + // Lidar com a criação da janela +}) +``` + +### Gerenciador de Eventos + +Lida com eventos personalizados e escuta de eventos do aplicativo. + +```go +// Eventos personalizados +app.Event.Emit("userAction", data) +cancelFunc := app.Event.On("userAction", func(e *CustomEvent) { + // Lidar com o evento +}) +app.Event.Off("userAction") +app.Event.Reset() // Remover todos os ouvintes + +// Eventos do aplicativo +app.Event.OnApplicationEvent(events.Common.ThemeChanged, func(e *ApplicationEvent) { + // Lidar com a mudança de tema do sistema +}) +``` + +### Gerenciador de Navegador + +Fornece integração com navegador para abrir URLs e arquivos. + +```go +// Abrir URLs e arquivos no navegador padrão +err := app.Browser.OpenURL("https://wails.io") +err := app.Browser.OpenFile("/path/to/document.pdf") +``` + +### Gerenciador de Ambiente + +Acesso às informações do ambiente do sistema. + +```go +// Obter informações do ambiente +env := app.Env.Info() +fmt.Printf("OS: %s, Arch: %s\n", env.OS, env.Arch) + +// Verificar o tema do sistema +if app.Env.IsDarkMode() { + // O modo escuro está ativo +} + +// Abrir o gerenciador de arquivos +err := app.Env.OpenFileManager("/path/to/folder", false) +``` + +### Gerenciador de Diálogos + +Acesso organizado a diálogos de arquivos e mensagens. + +```go +// Diálogos de arquivos +result, err := app.Dialog.OpenFile(). + AddFilter("Text Files", "*.txt"). + PromptForSingleSelection() + +result, err = app.Dialog.SaveFile(). + SetDefaultFilename("document.txt"). + PromptForSingleSelection() + +// Diálogos de mensagens +app.Dialog.Info(). + SetTitle("Information"). + SetMessage("Operation completed successfully"). + Show() + +app.Dialog.Error(). + SetTitle("Error"). + SetMessage("An error occurred"). + Show() +``` + +### Gerenciador de Menus + +Criação e gerenciamento de menus do aplicativo. + +```go +// Criar e definir o menu do aplicativo +menu := app.Menu.New() +fileMenu := menu.AddSubmenu("File") +fileMenu.Add("New").OnClick(func(ctx *Context) { + // Lidar com o clique no menu +}) + +app.Menu.Set(menu) + +// Exibir diálogo sobre +app.Menu.ShowAbout() +``` + +### Gerenciador de Atalhos de Teclado + +Gerenciamento dinâmico de atalhos de teclado globais. + +```go +// Adicionar atalhos de teclado +app.KeyBinding.Add("ctrl+n", func(window *WebviewWindow) { + // Lidar com Ctrl+N +}) + +app.KeyBinding.Add("ctrl+q", func(window *WebviewWindow) { + app.Quit() +}) + +// Remover atalhos de teclado +app.KeyBinding.Remove("ctrl+n") + +// Obter todos os atalhos +bindings := app.KeyBinding.GetAll() +``` + +### Gerenciador de Menus de Contexto + +Gerenciamento avançado de menus de contexto (para autores de bibliotecas). + +```go +// Criar e registrar menu de contexto +menu := app.ContextMenu.New() +app.ContextMenu.Add("myMenu", menu) + +// Recuperar menu de contexto +menu, exists := app.ContextMenu.Get("myMenu") + +// Remover menu de contexto +app.ContextMenu.Remove("myMenu") +``` + +### Gerenciador de Telas + +Gerenciamento de telas e transformações de coordenadas para configurações de múltiplos monitores. + +```go +// Obter informações da tela +screens := app.Screen.GetAll() +primary := app.Screen.GetPrimary() + +// Transformações de coordenadas +physicalPoint := app.Screen.DipToPhysicalPoint(logicalPoint) +logicalPoint := app.Screen.PhysicalToDipPoint(physicalPoint) + +// Detecção de tela +screen := app.Screen.ScreenNearestDipPoint(point) +screen = app.Screen.ScreenNearestDipRect(rect) +``` + +### Gerenciador de Área de Transferência + +Operações de área de transferência para leitura e gravação de texto. + +```go +// Definir texto na área de transferência +success := app.Clipboard.SetText("Hello World") +if !success { + // Lidar com erro +} + +// Obter texto da área de transferência +text, ok := app.Clipboard.Text() +if !ok { + // Lidar com erro +} else { + // Usar o texto +} +``` + +### Gerenciador da Bandeja do Sistema + +Criação e gerenciamento de ícones na bandeja do sistema. + +```go +// Criar bandeja do sistema +systray := app.SystemTray.New() +systray.SetLabel("My App") +systray.SetIcon(iconBytes) + +// Adicionar menu à bandeja do sistema +menu := app.Menu.New() +menu.Add("Open").OnClick(func(ctx *Context) { + // Lidar com o clique +}) +systray.SetMenu(menu) + +// Destruir a bandeja do sistema quando terminar +systray.Destroy() +``` \ No newline at end of file diff --git a/docs/src/content/docs/pt/contributing.mdx b/docs/src/content/docs/pt/contributing.mdx new file mode 100644 index 00000000000..8308ab1a77b --- /dev/null +++ b/docs/src/content/docs/pt/contributing.mdx @@ -0,0 +1,275 @@ +--- +title: Contribuindo +description: Contribua com o Wails +sidebar: + order: 100 +--- + +import { Card, CardGrid } from "@astrojs/starlight/components"; + +## Bem-vindos, Colaboradores! + +Agradecemos suas contribuições para o Wails! Seja corrigindo bugs, adicionando recursos ou melhorando a documentação, seu auxílio é muito apreciado. + +## Formas de Contribuir + +### 1. Relatar Problemas + +Encontrou um bug? [Abra uma issue](https://github.com/wailsapp/wails/issues/new) com: +- Descrição clara +- Passos para reproduzir +- Comportamento esperado vs. real +- Informações do sistema +- Exemplos de código + +### 2. Melhorar a Documentação + +Melhorias na documentação são sempre bem-vindas: +- Corrigir erros de digitação e imprecisões +- Adicionar exemplos +- Esclarecer explicações +- Traduzir conteúdo + +### 3. Enviar Código + +Contribua com código através de pull requests: +- Correções de bugs +- Novos recursos +- Melhorias de desempenho +- Testes + +## Começando + +### Fork e Clone + +```bash +# Faça um fork do repositório no GitHub +# Em seguida, clone seu fork +git clone https://github.com/YOUR_USERNAME/wails.git +cd wails + +# Adicione o repositório original (upstream) +git remote add upstream https://github.com/wailsapp/wails.git +``` + +### Compilar a partir do Código Fonte + +```bash +# Instale as dependências +go mod download + +# Compile a CLI do Wails +cd v3/cmd/wails3 +go build + +# Teste sua compilação +./wails3 version +``` + +### Executar Testes + +```bash +# Execute todos os testes +go test ./... + +# Execute testes de pacotes específicos +go test ./v3/pkg/application + +# Execute com cobertura de código +go test -cover ./... +``` + +## Fazendo Alterações + +### Criar um Branch + +```bash +# Atualize a main +git checkout main +git pull upstream main + +# Crie um branch para o recurso +git checkout -b feature/my-feature +``` + +### Faça Suas Alterações + +1. **Escreva o código** seguindo as convenções do Go +2. **Adicione testes** para a nova funcionalidade +3. **Atualize a documentação** se necessário +4. **Execute os testes** para garantir que nada quebrou +5. **Faça o commit das alterações** com mensagens claras + +### Diretrizes de Commit + +```bash +# Bons commits +git commit -m "fix: resolve window focus issue on macOS" +git commit -m "feat: add support for custom window chrome" +git commit -m "docs: improve bindings documentation" + +# Use commits convencionais: +# - feat: Novo recurso +# - fix: Correção de bug +# - docs: Documentação +# - test: Testes +# - refactor: Refatoração de código +# - chore: Manutenção +``` + +### Enviar Pull Request + +```bash +# Envie para seu fork +git push origin feature/my-feature + +# Abra o pull request no GitHub +# Forneça uma descrição clara +# Referencie as issues relacionadas +``` + +## Diretrizes de Pull Request + +### Boa Descrição de PR + +```markdown +## Descrição +Breve descrição das alterações + +## Alterações +- Adicionado recurso X +- Corrigido bug Y +- Documentação atualizada + +## Testes +- Testado no macOS 14 +- Testado no Windows 11 +- Todos os testes passando + +## Issues Relacionadas +Fixes #123 +``` + +### Checklist do PR + +- [ ] O código segue as convenções do Go +- [ ] Testes adicionados/atualizados +- [ ] Documentação atualizada +- [ ] Todos os testes passando +- [ ] Sem breaking changes (ou documentadas) +- [ ] Mensagens de commit claras + +## Diretrizes de Código + +### Estilo de Código Go + +```go +// ✅ Bom: Claro, documentado, testado +// ProcessData processa os dados de entrada e retorna o resultado. +// Retorna um erro se os dados forem inválidos. +func ProcessData(data string) (string, error) { + if data == "" { + return "", errors.New("data cannot be empty") + } + + result := process(data) + return result, nil +} + +// ❌ Ruim: Sem docs, sem tratamento de erros +func ProcessData(data string) string { + return process(data) +} +``` + +### Testes + +```go +func TestProcessData(t *testing.T) { + tests := []struct { + name string + input string + want string + wantErr bool + }{ + {"valid input", "test", "processed", false}, + {"empty input", "", "", true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ProcessData(tt.input) + if (err != nil) != tt.wantErr { + t.Errorf("ProcessData() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("ProcessData() = %v, want %v", got, tt.want) + } + }) + } +} +``` + +## Documentação + +### Escrevendo Documentação + +A documentação usa Starlight (Astro): + +```bash +cd docs +npm install +npm run dev +``` + +### Estilo de Documentação + +- Use ortografia do inglês internacional +- Comece com o problema +- Forneça exemplos funcionais +- Inclua solução de problemas +- Faça referência cruzada ao conteúdo relacionado + +## Comunidade + +### Obter Ajuda + +- **Discord:** [Junte-se à nossa comunidade](https://discord.gg/JDdSxwjhGf) +- **GitHub Discussions:** Faça perguntas +- **GitHub Issues:** Relate bugs + +### Código de Conduta + +Seja respeitoso, inclusivo e profissional. Estamos todos aqui para construir um ótimo software juntos. + +## Reconhecimento + +Os colaboradores são reconhecidos em: +- Notas de lançamento +- Lista de colaboradores +- Insights do GitHub + +Obrigado por contribuir com o Wails! 🎉 + +## Próximos Passos + + + + Visite o repositório do Wails. + + [Ver no GitHub →](https://github.com/wailsapp/wails) + + + + Junte-se à comunidade. + + [Entrar no Discord →](https://discord.gg/JDdSxwjhGf) + + + + Leia a documentação. + + [Navegar pela Documentação →](/pt/quick-start/why-wails) + + \ No newline at end of file diff --git a/docs/src/content/docs/pt/contributing/architecture.mdx b/docs/src/content/docs/pt/contributing/architecture.mdx new file mode 100644 index 00000000000..0f4b0a3525c --- /dev/null +++ b/docs/src/content/docs/pt/contributing/architecture.mdx @@ -0,0 +1,98 @@ +--- +title: Arquitetura do Wails v3 +description: Diagramas detalhados e explicações de cada componente interno do Wails v3 +sidebar: + order: 1 +--- + +O Wails v3 é um **framework desktop full-stack** composto por um runtime em Go, +uma ponte JavaScript, uma cadeia de ferramentas orientada a tarefas e uma coleção de templates que +permitem lançar aplicativos nativos impulsionados por tecnologias web modernas. + +Esta página apresenta a *visão geral* em quatro diagramas: + +1. **Arquitetura Geral** – como cada subsistema se conecta +2. **Fluxo do Runtime** – o que acontece quando JS chama Go e vice-versa +3. **Desenvolvimento vs Produção** – dois modos do servidor de ativos +4. **Implementações de Plataforma** – onde o código específico do sistema operacional reside + +--- + +## 1 · Arquitetura Geral + +**Wails v3 – Pilha de Alto Nível** + +{/* +TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. +The previous D2 code block was causing MDX parsing errors in the build pipeline. +*/} + +**[Placeholder do Diagrama da Pilha de Alto Nível]** + +--- + +## 2 · Fluxo de Chamada do Runtime + +**Runtime – Caminho de Chamada JavaScript ⇄ Go** + +{/* +TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. +The previous D2 code block was causing MDX parsing errors in the build pipeline. +*/} + +**[Placeholder do Diagrama de Fluxo de Chamada do Runtime]** + +Pontos-chave: + +* **Sem HTTP / IPC** – a ponte utiliza o canal em memória da WebView nativa +* **IDs de Método** – o hash FNV determinístico permite lookup O(1) em Go +* **Promises** – erros são propagados como rejeições com stack trace e código + +--- + +## 3 · Fluxo de Ativos: Desenvolvimento vs Produção + +**Servidor de Ativos Dev ↔ Prod** + +{/* +TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. +The previous D2 code block was causing MDX parsing errors in the build pipeline. +*/} + +**[Placeholder do Diagrama de Fluxo de Ativos]** + +* Em **dev**, o servidor faz proxy de caminhos desconhecidos para o servidor de live-reload + do framework e serve ativos estáticos diretamente do disco. +* Em **prod**, a mesma API é suportada por `go:embed`, produzindo um + binário sem dependências. + +--- + +## 4 · Divisão do Runtime Específico por Plataforma + +**Arquivos de Runtime por SO** + +{/* +TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. +The previous D2 code block was causing MDX parsing errors in the build pipeline. +*/} + +**[Placeholder do Diagrama de Divisão por Plataforma]** + +Cada funcionalidade segue este padrão: + +1. **Interface comum** em `pkg/application` +2. **Entrada do processador de mensagens** em `pkg/application/messageprocessor_*.go` +3. **Implementação** por SO sob `internal/runtime/*.go`, protegida por build tags + +Funcionalidades ausentes em um SO devem retornar `ErrCapability` e registrar +a disponibilidade via `internal/capabilities`. + +--- + +## Resumo + +Estes diagramas delineiam **onde o código reside**, **como os dados se movem** e +**quais camidas possuem quais responsabilidades**. +Mantenha-os à mão enquanto explora as páginas detalhadas que se seguem – elas são seu +mapa para a árvore de fontes do Wails v3. \ No newline at end of file diff --git a/docs/src/content/docs/pt/contributing/architecture/bindings.mdx b/docs/src/content/docs/pt/contributing/architecture/bindings.mdx new file mode 100644 index 00000000000..04186ebcd63 --- /dev/null +++ b/docs/src/content/docs/pt/contributing/architecture/bindings.mdx @@ -0,0 +1,156 @@ +--- +title: Sistema de Bindings +description: Como o sistema de bindings coleta, processa e gera código JavaScript/TypeScript +sidebar: + order: 1 +--- + +import { FileTree } from "@astrojs/starlight/components"; + +Este guia explica como o sistema de bindings do Wails funciona internamente, fornecendo insights para desenvolvedores que desejam entender a mecânica por trás da geração automática de código. + +## Visão Geral da Arquitetura + +O sistema de bindings do Wails consiste em três componentes principais: + +1. **Coleta**: Analisa o código Go para extrair informações sobre serviços, modelos e outras declarações +2. **Configuração**: Gerencia configurações e opções para o processo de geração de bindings +3. **Renderização**: Gera código JavaScript/TypeScript com base nas informações coletadas + + +- internal/generator/ + - collect/ # Análise de pacotes e extração de informações + - config/ # Estruturas e interfaces de configuração + - render/ # Geração de código para JS/TS + + +## Processo de Coleta + +O processo de coleta é responsável por analisar os pacotes Go e extrair informações sobre serviços, modelos e outras declarações. Isso é tratado pelo pacote `collect`. + +### Componentes Principais + +- **Collector**: Gerencia informações do pacote e armazena em cache os dados coletados +- **Package**: Representa um pacote Go sendo analisado e armazena serviços, modelos e diretivas coletados +- **Service**: Coleta informações sobre tipos de serviço e seus métodos +- **Model**: Coleta informações detalhadas sobre tipos de modelo, incluindo campos, valores e parâmetros de tipo +- **Directive**: Analisa e interpreta as diretivas `//wails:` no código-fonte Go + +### Fluxo de Coleta + +1. O collector escaneia os pacotes Go especificados no projeto +2. Ele identifica tipos de serviço (structs com métodos que serão expostos ao frontend) +3. Para cada serviço, ele coleta informações sobre seus métodos +4. Ele identifica tipos de modelo (structs usadas como parâmetros ou valores de retorno em métodos de serviço) +5. Para cada modelo, ele coleta informações sobre seus campos e parâmetros de tipo +6. Ele processa quaisquer diretivas `//wails:` encontradas no código + +## Processo de Renderização + +O processo de renderização é responsável por gerar código JavaScript/TypeScript com base nas informações coletadas. Isso é tratado pelo pacote `render`. + +### Componentes Principais + +- **Renderer**: Orquestra a renderização de arquivos de serviço, modelo e índice +- **Module**: Representa um único módulo JavaScript/TypeScript gerado +- **Templates**: Modelos de texto usados para geração de código + +### Fluxo de Renderização + +1. Para cada serviço, o renderer gera um arquivo JavaScript/TypeScript com funções que espelham os métodos do serviço +2. Para cada modelo, o renderer gera uma classe JavaScript/TypeScript que espelha a struct do modelo +3. O renderer gera arquivos de índice que reexportam todos os serviços e modelos +4. O renderer aplica quaisquer injeções de código personalizadas especificadas pelas diretivas `//wails:inject` + +## Mapeamento de Tipos + +Um dos aspectos mais importantes do sistema de bindings é como os tipos Go são mapeados para tipos JavaScript/TypeScript. Aqui está um resumo do mapeamento: + +| Tipo Go | Tipo JavaScript | Tipo TypeScript | +|---------|----------------|----------------| +| `bool` | `boolean` | `boolean` | +| `int`, `int8`, `int16`, `int32`, `int64`, `uint`, `uint8`, `uint16`, `uint32`, `uint64`, `float32`, `float64` | `number` | `number` | +| `string` | `string` | `string` | +| `[]byte` | `Uint8Array` | `Uint8Array` | +| `[]T` | `Array` | `T[]` | +| `map[K]V` | `Object` | `Record` | +| `struct` | `Object` | Classe personalizada | +| `interface{}` | `any` | `any` | +| `*T` | `T \| null` | `T \| null` | +| `func` | Não suportado | Não suportado | +| `chan` | Não suportado | Não suportado | + +## Sistema de Diretivas + +O sistema de bindings suporta várias diretivas que podem ser usadas para personalizar o código gerado. Essas diretivas são adicionadas como comentários no seu código Go. + +### Diretivas Disponíveis + +- `//wails:inject`: Injeta código JavaScript/TypeScript personalizado nos bindings gerados +- `//wails:include`: Inclui arquivos adicionais com os bindings gerados +- `//wails:internal`: Marca um tipo ou método como interno, impedindo que seja exportado para o frontend +- `//wails:ignore`: Ignora completamente um método durante a geração de bindings +- `//wails:id`: Especifica um ID personalizado para um método, substituindo o ID padrão baseado em hash + +### Processamento de Diretivas + +1. Durante a fase de coleta, o collector identifica e analisa as diretivas no código Go +2. As diretivas são armazenadas junto com as declarações correspondentes (serviços, métodos, modelos, etc.) +3. Durante a fase de renderização, o renderer aplica as diretivas para personalizar o código gerado + +## Recursos Avançados + +### Geração Condicional de Código + +O sistema de bindings suporta geração condicional de código usando um prefixo de condição de dois caracteres para as diretivas `include` e `inject`: + +``` + + + +
+

Application Report

+

Generated: {{.Timestamp}}

+
+
+ + {{range .Items}} +

{{.}}

+ {{end}} +
+ +` + + // Write report to file + file, err := os.Create(reportPath) + if err != nil { + return err + } + defer file.Close() + + t, err := template.New("report").Parse(tmpl) + if err != nil { + return err + } + + err = t.Execute(file, data) + if err != nil { + return err + } + + // Open in browser + return app.Browser.OpenFile(reportPath) +} +``` + +### Ferramentas de Desenvolvimento + +Abra recursos de desenvolvimento durante o desenvolvimento: + +```go +func setupDevelopmentMenu(app *application.App) { + if !app.Env.Info().Debug { + return // Only show in debug mode + } + + menu := app.Menu.New() + devMenu := menu.AddSubmenu("Development") + + devMenu.Add("Open DevTools").OnClick(func(ctx *application.Context) { + // This would open browser devtools if available + window := app.Window.Current() + if window != nil { + window.OpenDevTools() + } + }) + + devMenu.Add("View Source").OnClick(func(ctx *application.Context) { + // Open source code repository + app.Browser.OpenURL("https://github.com/youruser/yourapp") + }) + + devMenu.Add("API Documentation").OnClick(func(ctx *application.Context) { + // Open local API docs + app.Browser.OpenURL("http://localhost:8080/docs") + }) +} +``` + +## Tratamento de Erros + +### Tratamento de Erros Graceful + +Sempre trate erros potenciais ao abrir URLs ou arquivos: + +```go +func openURLWithFallback(app *application.App, url string, fallbackMessage string) { + err := app.Browser.OpenURL(url) + if err != nil { + app.Logger.Error("Failed to open URL", "url", url, "error", err) + + // Show fallback dialog with URL + dialog := app.Dialog.Info() + dialog.SetTitle("Unable to Open Link") + dialog.SetMessage(fmt.Sprintf("%s\n\nURL: %s", fallbackMessage, url)) + dialog.Show() + } +} + +// Usage +openURLWithFallback(app, + "https://docs.example.com", + "Please open the following URL manually in your browser:") +``` + +### Feedback ao Usuário + +Forneça feedback quando as operações forem bem-sucedidas ou falharem: + +```go +func openURLWithFeedback(app *application.App, url string) { + err := app.Browser.OpenURL(url) + if err != nil { + // Show error dialog + app.Dialog.Error(). + SetTitle("Browser Error"). + SetMessage(fmt.Sprintf("Could not open URL: %s", err.Error())). + Show() + } else { + // Optionally show success notification + app.Logger.Info("URL opened successfully", "url", url) + } +} +``` + +## Considerações de Plataforma + + + + + No macOS: + + - Usa o comando `open` para iniciar o navegador padrão- Respeita a configuração do navegador padrão do usuário nas Preferências do Sistema +- Pode solicitar permissão se o aplicativo estiver em sandbox +- Lida corretamente com URLs `file://` para arquivos locais + + + + + + No Windows: + + - Usa a API do Shell do Windows para abrir URLs + - Respeita a configuração do navegador padrão nas Configurações do Windows + - Lida corretamente com os formatos de caminho do Windows + - Pode exibir avisos de segurança para URLs não confiáveis + + + + + + No Linux: + + - Tenta usar `xdg-open` primeiro, caindo em outras metodologias se necessário + - O comportamento varia conforme o ambiente de área de trabalho + - Respeita a variável de ambiente `BROWSER` se estiver definida + - Pode exigir pacotes adicionais em instalações mínimas + + + + +## Melhores Práticas + +1. **Sempre Lidar com Erros**: As operações do navegador podem falhar por vários motivos: + ```go + if err := app.Browser.OpenURL(url); err != nil { + app.Logger.Error("Failed to open browser", "error", err) + // Provide fallback or user notification + } + ``` + +2. **Validar URLs**: Certifique-se de que as URLs estejam bem formadas antes de abri-las: + ```go + func isValidHTTPURL(str string) bool { + u, err := url.Parse(str) + return err == nil && (u.Scheme == "http" || u.Scheme == "https") + } + ``` + +3. **Confirmação do Usuário**: Para links externos, considere pedir permissão ao usuário: + ```go + // Show confirmation dialog before opening external links + confirmAndOpen(app, "https://external-site.com") + ``` + +4. **Caminhos de Arquivo Seguros**: Ao abrir arquivos, certifique-se de que os caminhos sejam seguros: + ```go + func openSafeFile(app *application.App, filename string) error { + // Ensure file exists and is readable + if _, err := os.Stat(filename); err != nil { + return err + } + return app.Browser.OpenFile(filename) + } + ``` + +## Exemplo Completo + +Aqui está um exemplo completo mostrando vários padrões de integração do navegador: + +```go +package main + +import ( + "fmt" + "os" + "path/filepath" + "github.com/wailsapp/wails/v3/pkg/application" +) + +func main() { + app := application.New(application.Options{ + Name: "Browser Integration Demo", + }) + + // Setup menu with browser actions + setupMenu(app) + + // Create main window + window := app.Window.New() + window.SetTitle("Browser Integration") + + err := app.Run() + if err != nil { + panic(err) + } +} + +func setupMenu(app *application.App) { + menu := app.Menu.New() + + // File menu + fileMenu := menu.AddSubmenu("File") + fileMenu.Add("Generate Report").OnClick(func(ctx *application.Context) { + generateHTMLReport(app) + }) + + // Help menu + helpMenu := menu.AddSubmenu("Help") + helpMenu.Add("Documentation").OnClick(func(ctx *application.Context) { + openWithConfirmation(app, "https://docs.example.com") + }) + helpMenu.Add("Support").OnClick(func(ctx *application.Context) { + openWithConfirmation(app, "https://support.example.com") + }) + + app.Menu.Set(menu) +} + +func openWithConfirmation(app *application.App, url string) { + dialog := app.Dialog.Question() + dialog.SetTitle("Open External Link") + dialog.SetMessage(fmt.Sprintf("Open %s in your browser?", url)) + + dialog.AddButton("Open").OnClick(func() { + if err := app.Browser.OpenURL(url); err != nil { + showError(app, "Failed to open URL", err) + } + }) + + dialog.AddButton("Cancel") + dialog.Show() +} + +func generateHTMLReport(app *application.App) { + // Create temporary HTML file + tmpDir := os.TempDir() + reportPath := filepath.Join(tmpDir, "demo_report.html") + + html := ` + + + + Demo Report + + + +
+

Application Report

+

This is a sample report generated by the application.

+
+
+

Report Details

+

This report was generated to demonstrate browser integration.

+
+ +` + + err := os.WriteFile(reportPath, []byte(html), 0644) + if err != nil { + showError(app, "Failed to create report", err) + return + } + + // Open in browser + err = app.Browser.OpenFile(reportPath) + if err != nil { + showError(app, "Failed to open report", err) + } +} + +func showError(app *application.App, message string, err error) { + app.Dialog.Error(). + SetTitle("Error"). + SetMessage(fmt.Sprintf("%s: %v", message, err)). + Show() +} +``` + +:::tip[Pro Tip] +Consider providing fallback mechanisms for when browser operations fail, such as copying URLs to clipboard or showing them in a dialog for manual opening. +::: + +:::danger[Warning] +Always validate URLs and file paths before opening them to prevent security issues. Be cautious about opening user-provided URLs without validation. +::: \ No newline at end of file diff --git a/docs/src/content/docs/pt/features/clipboard/basics.mdx b/docs/src/content/docs/pt/features/clipboard/basics.mdx new file mode 100644 index 00000000000..f9ac82e91d1 --- /dev/null +++ b/docs/src/content/docs/pt/features/clipboard/basics.mdx @@ -0,0 +1,409 @@ +--- +title: Operações de Área de Transferência +description: Copie e cole texto com a área de transferência do sistema +sidebar: + order: 1 +--- + +import { Card, CardGrid } from "@astrojs/starlight/components"; + +## Operações de Área de Transferência + +O Wails fornece uma **API unificada de área de transferência** que funciona em todas as plataformas. Copie e cole texto com métodos simples e consistentes no Windows, macOS e Linux. + +## Início Rápido + +```go +// Copia texto para a área de transferência +app.Clipboard.SetText("Hello, World!") + +// Obtém texto da área de transferência +text, ok := app.Clipboard.Text() +if ok { + fmt.Println("Área de transferência:", text) +} +``` + +**É isso!** Acesso à área de transferência multiplataforma. + +## Copiando Texto + +### Cópia Básica + +```go +success := app.Clipboard.SetText("Texto para copiar") +if !success { + app.Logger.Error("Falha ao copiar para a área de transferência") +} +``` + +**Retorna:** `bool` - `true` se bem-sucedido, `false` caso contrário + +### Cópia a partir de Serviço + +```go +type ClipboardService struct { + app *application.Application +} + +func (c *ClipboardService) CopyToClipboard(text string) bool { + return c.app.Clipboard.SetText(text) +} +``` + +**Chamar do JavaScript:** + +```javascript +import { CopyToClipboard } from './bindings/myapp/clipboardservice' + +await CopyToClipboard("Texto para copiar") +``` + +### Cópia com Feedback + +```go +func copyWithFeedback(text string) { + if app.Clipboard.SetText(text) { + app.Dialog.Info(). + SetTitle("Copiado"). + SetMessage("Texto copiado para a área de transferência!"). + Show() + } else { + app.Dialog.Error(). + SetTitle("Falha na Cópia"). + SetMessage("Falha ao copiar para a área de transferência."). + Show() + } +} +``` + +## Colando Texto + +### Colagem Básica + +```go +text, ok := app.Clipboard.Text() +if !ok { + app.Logger.Error("Falha ao ler a área de transferência") + return +} + +fmt.Println("Texto da área de transferência:", text) +``` + +**Retorna:** `(string, bool)` - Texto e flag de sucesso + +### Colagem a partir de Serviço + +```go +func (c *ClipboardService) PasteFromClipboard() string { + text, ok := c.app.Clipboard.Text() + if !ok { + return "" + } + return text +} +``` + +**Chamar do JavaScript:** + +```javascript +import { PasteFromClipboard } from './bindings/myapp/clipboardservice' + +const text = await PasteFromClipboard() +console.log("Colado:", text) +``` + +### Colagem com Validação + +```go +func pasteText() (string, error) { + text, ok := app.Clipboard.Text() + if !ok { + return "", errors.New("área de transferência vazia ou indisponível") + } + + // Valida + if len(text) == 0 { + return "", errors.New("a área de transferência está vazia") + } + + if len(text) > 10000 { + return "", errors.New("texto da área de transferência muito grande") + } + + return text, nil +} +``` + +## Exemplos Completos + +### Botão de Cópia + +**Go:** + +```go +type TextService struct { + app *application.Application +} + +func (t *TextService) CopyText(text string) error { + if !t.app.Clipboard.SetText(text) { + return errors.New("falha ao copiar") + } + return nil +} +``` + +**JavaScript:** + +```javascript +import { CopyText } from './bindings/myapp/textservice' + +async function copyToClipboard(text) { + try { + await CopyText(text) + showNotification("Copiado para a área de transferência!") + } catch (error) { + showError("Falha ao copiar: " + error) + } +} + +// Uso +document.getElementById('copy-btn').addEventListener('click', () => { + const text = document.getElementById('text').value + copyToClipboard(text) +}) +``` + +### Colar e Processar + +**Go:** + +```go +type DataService struct { + app *application.Application +} + +func (d *DataService) PasteAndProcess() (string, error) { + // Obtém texto da área de transferência + text, ok := d.app.Clipboard.Text() + if !ok { + return "", errors.New("área de transferência indisponível") + } + + // Processa o texto + processed := strings.TrimSpace(text) + processed = strings.ToUpper(processed) + + return processed, nil +} +``` + +**JavaScript:** + +```javascript +import { PasteAndProcess } from './bindings/myapp/dataservice' + +async function pasteAndProcess() { + try { + const result = await PasteAndProcess() + document.getElementById('output').value = result + } catch (error) { + showError("Falha ao colar: " + error) + } +} +``` + +### Copiar Múltiplos Formatos + +```go +type CopyService struct { + app *application.Application +} + +func (c *CopyService) CopyAsPlainText(text string) bool { + return c.app.Clipboard.SetText(text) +} + +func (c *CopyService) CopyAsJSON(data interface{}) bool { + jsonBytes, err := json.MarshalIndent(data, "", " ") + if err != nil { + return false + } + return c.app.Clipboard.SetText(string(jsonBytes)) +} + +func (c *CopyService) CopyAsCSV(rows [][]string) bool { + var buf bytes.Buffer + writer := csv.NewWriter(&buf) + + for _, row := range rows { + if err := writer.Write(row); err != nil { + return false + } + } + + writer.Flush() + return c.app.Clipboard.SetText(buf.String()) +} +``` + +### Monitor de Área de Transferência + +```go +type ClipboardMonitor struct { + app *application.Application + lastText string + ticker *time.Ticker + stopChan chan bool +} + +func NewClipboardMonitor(app *application.Application) *ClipboardMonitor { + return &ClipboardMonitor{ + app: app, + stopChan: make(chan bool), + } +} + +func (cm *ClipboardMonitor) Start() { + cm.ticker = time.NewTicker(1 * time.Second) + + go func() { + for { + select { + case <-cm.ticker.C: + cm.checkClipboard() + case <-cm.stopChan: + return + } + } + }() +} + +func (cm *ClipboardMonitor) Stop() { + if cm.ticker != nil { + cm.ticker.Stop() + } + cm.stopChan <- true +} + +func (cm *ClipboardMonitor) checkClipboard() { + text, ok := cm.app.Clipboard.Text() + if !ok { + return + } + + if text != cm.lastText { + cm.lastText = text + cm.app.Event.Emit("clipboard-changed", text) + } +} +``` + +### Cópia com Histórico + +```go +type ClipboardHistory struct { + app *application.Application + history []string + maxSize int +} + +func NewClipboardHistory(app *application.Application) *ClipboardHistory { + return &ClipboardHistory{ + app: app, + history: make([]string, 0), + maxSize: 10, + } +} + +func (ch *ClipboardHistory) Copy(text string) bool { + if !ch.app.Clipboard.SetText(text) { + return false + } + + // Adiciona ao histórico + ch.history = append([]string{text}, ch.history...) + + // Limita o tamanho + if len(ch.history) > ch.maxSize { + ch.history = ch.history[:ch.maxSize] + } + + return true +} + +func (ch *ClipboardHistory) GetHistory() []string { + return ch.history +} + +func (ch *ClipboardHistory) RestoreFromHistory(index int) bool { + if index < 0 || index >= len(ch.history) { + return false + } + + return ch.app.Clipboard.SetText(ch.history[index]) +} +``` + +## Integração com Frontend + +### Usando a API de Área de Transferência do Navegador + +Para texto simples, você pode usar a API de área de transferência do navegador: + +```javascript +// Copia +async function copyText(text) { + try { + await navigator.clipboard.writeText(text) + console.log("Copiado!") + } catch (error) { + console.error("Falha ao copiar:", error) + } +} + +// Cola +async function pasteText() { + try { + const text = await navigator.clipboard.readText() + return text + } catch (error) { + console.error("Falha ao colar:", error) + return "" + } +} +``` + +**Nota:** A API de área de transferência do navegador requer HTTPS ou localhost, e permissão do usuário. + +### Usando a Área de Transferência do Wails + +Para acesso à área de transferência em todo o sistema: + +```javascript +import { CopyToClipboard, PasteFromClipboard } from './bindings/myapp/clipboardservice' + +// Copia +async function copy(text) { + const success = await CopyToClipboard(text) + if (success) { + console.log("Copiado!") + } +} + +// Cola +async function paste() { + const text = await PasteFromClipboard() + return text +} +``` + +## Melhores Práticas + +### ✅ Faça + +- **Verifique os valores de retorno** - Lidere com falhas de forma graciosa--- + +**Perguntas?** Pergunte no [Discord](https://discord.gg/JDdSxwjhGf) ou verifique os [exemplos de área de transferência](https://github.com/wailsapp/wails/tree/master/v3/examples). \ No newline at end of file diff --git a/docs/src/content/docs/pt/features/dialogs/custom.mdx b/docs/src/content/docs/pt/features/dialogs/custom.mdx new file mode 100644 index 00000000000..cc26d4124d0 --- /dev/null +++ b/docs/src/content/docs/pt/features/dialogs/custom.mdx @@ -0,0 +1,383 @@ +--- +title: Diálogos personalizados +description: Crie diálogos personalizados em suas aplicações Wails +sidebar: + order: 4 +--- + +import { Card, CardGrid } from "@astrojs/starlight/components"; + +## Diálogos personalizados + +Crie **janelas de diálogo personalizadas** usando janelas Wails padrão com comportamento semelhante ao de diálogos. Construa formulários personalizados, validação complexa de entrada, aparência com marca registrada e conteúdo rico (imagens, vídeos), mantendo os padrões de diálogo familiares. + +## Início rápido + +```go +// Create custom dialog window +dialog := app.Window.NewWithOptions(application.WebviewWindowOptions{ + Title: "Custom dialog", + Width: 400, + Height: 300, + AlwaysOnTop: true, + Frameless: true, + Hidden: true, +}) + +// Load custom UI +dialog.SetURL("http://wails.localhost/dialog.html") + +// Show as modal +dialog.Show() +dialog.SetFocus() +``` + +**É isso!** Interface personalizada com comportamento de diálogo. + +## Criando diálogos personalizados + +### Diálogo personalizado básico + +```go +type Customdialog struct { + window *application.WebviewWindow + result chan string +} + +func NewCustomdialog(app *application.Application) *Customdialog { + dialog := &Customdialog{ + result: make(chan string, 1), + } + + dialog.window = app.Window.NewWithOptions(application.WebviewWindowOptions{ + Title: "Custom dialog", + Width: 400, + Height: 300, + AlwaysOnTop: true, + Resizable: false, + Hidden: true, + }) + + return dialog +} + +func (d *Customdialog) Show() string { + d.window.Show() + d.window.SetFocus() + + // Wait for result + return <-d.result +} + +func (d *Customdialog) Close(result string) { + d.result <- result + d.window.Close() +} +``` + +### Diálogo modal + +```go +func ShowModaldialog(parent *application.WebviewWindow, title string) string { + // Create dialog + dialog := app.Window.NewWithOptions(application.WebviewWindowOptions{ + Title: title, + Width: 400, + Height: 200, + Parent: parent, + AlwaysOnTop: true, + Resizable: false, + }) + + // Disable parent + parent.SetEnabled(false) + + // Re-enable parent on close + dialog.OnClose(func() bool { + parent.SetEnabled(true) + parent.SetFocus() + return true + }) + + dialog.Show() + + return waitForResult(dialog) +} +``` + +### Diálogo de formulário + +```go +type Formdialog struct { + window *application.WebviewWindow + data map[string]interface{} + done chan bool +} + +func NewFormdialog(app *application.Application) *Formdialog { + fd := &Formdialog{ + data: make(map[string]interface{}), + done: make(chan bool, 1), + } + + fd.window = app.Window.NewWithOptions(application.WebviewWindowOptions{ + Title: "Enter Information", + Width: 500, + Height: 400, + Frameless: true, + Hidden: true, + }) + + return fd +} + +func (fd *Formdialog) Show() (map[string]interface{}, bool) { + fd.window.Show() + fd.window.SetFocus() + + ok := <-fd.done + return fd.data, ok +} + +func (fd *Formdialog) Submit(data map[string]interface{}) { + fd.data = data + fd.done <- true + fd.window.Close() +} + +func (fd *Formdialog) Cancel() { + fd.done <- false + fd.window.Close() +} +``` + +## Padrões de diálogo + +### Diálogo de confirmação + +```go +func ShowConfirmdialog(message string) bool { + dialog := app.Window.NewWithOptions(application.WebviewWindowOptions{ + Title: "Confirm", + Width: 400, + Height: 150, + AlwaysOnTop: true, + Frameless: true, + }) + + // Pass message to dialog + dialog.OnReady(func() { + dialog.EmitEvent("set-message", message) + }) + + result := make(chan bool, 1) + + // Handle responses + app.Event.On("confirm-yes", func(e *application.CustomEvent) { + result <- true + dialog.Close() + }) + + app.Event.On("confirm-no", func(e *application.CustomEvent) { + result <- false + dialog.Close() + }) + + dialog.Show() + return <-result +} +``` + +**Frontend (HTML/JS):** + +```html +
+

+
+ + +
+
+ + +``` + +### Diálogo de entrada + +```go +func ShowInputdialog(prompt string, defaultValue string) (string, bool) { + dialog := app.Window.NewWithOptions(application.WebviewWindowOptions{ + Title: "Input", + Width: 400, + Height: 150, + Frameless: true, + }) + + result := make(chan struct { + value string + ok bool + }, 1) + + dialog.OnReady(func() { + dialog.EmitEvent("set-prompt", map[string]string{ + "prompt": prompt, + "default": defaultValue, + }) + }) + + app.Event.On("input-submit", func(e *application.CustomEvent) { + result <- struct { + value string + ok bool + }{e.Data.(string), true} + dialog.Close() + }) + + app.Event.On("input-cancel", func(e *application.CustomEvent) { + result <- struct { + value string + ok bool + }{"", false} + dialog.Close() + }) + + dialog.Show() + r := <-result + return r.value, r.ok +} +``` + +### Diálogo de progresso + +```go +type Progressdialog struct { + window *application.WebviewWindow +} + +func NewProgressdialog(title string) *Progressdialog { + pd := &Progressdialog{} + + pd.window = app.Window.NewWithOptions(application.WebviewWindowOptions{ + Title: title, + Width: 400, + Height: 150, + Frameless: true, + }) + + return pd +} + +func (pd *Progressdialog) Show() { + pd.window.Show() +} + +func (pd *Progressdialog) UpdateProgress(current, total int, message string) { + pd.window.EmitEvent("progress-update", map[string]interface{}{ + "current": current, + "total": total, + "message": message, + }) +} + +func (pd *Progressdialog) Close() { + pd.window.Close() +} +``` + +**Uso:** + +```go +func processFiles(files []string) { + progress := NewProgressdialog("Processing Files") + progress.Show() + + for i, file := range files { + progress.UpdateProgress(i+1, len(files), + fmt.Sprintf("Processing %s...", filepath.Base(file))) + + processFile(file) + } + + progress.Close() +} +``` + +## Exemplos completos + +### Diálogo de login + +**Go:** + +```go +type Logindialog struct { + window *application.WebviewWindow + result chan struct { + username string + password string + ok bool + } +} + +func NewLogindialog(app *application.Application) *Logindialog { + ld := &Logindialog{ + result: make(chan struct { + username string + password string + ok bool + }, 1), + } + + ld.window = app.Window.NewWithOptions(application.WebviewWindowOptions{ + Title: "Login", + Width: 400, + Height: 250, + Frameless: true, + }) + + return ld +} + +func (ld *Logindialog) Show() (string, string, bool) { + ld.window.Show() + ld.window.SetFocus() + + r := <-ld.result + return r.username, r.password, r.ok +} + +func (ld *Logindialog) Submit(username, password string) { + ld.result <- struct { + username string + password string + ok bool + }{username, password, true} + ld.window.Close() +} + +func (ld *Logindialog) Cancel() { + ld.result <- struct { + username string + password string + ok bool + }{"", "", false} + ld.window.Close() +} +``` + +**Frontend:** + +```html +