diff --git a/v3/examples/notifications/frontend/index.html b/v3/examples/notifications/frontend/index.html
deleted file mode 100644
index 88daa5e2f..000000000
--- a/v3/examples/notifications/frontend/index.html
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
- Wails App
-
-
-
-
-
Wails + Javascript
-
-
-
-
-
diff --git a/v3/examples/notifications/frontend/main.js b/v3/examples/notifications/frontend/main.js
deleted file mode 100644
index 18dd0214c..000000000
--- a/v3/examples/notifications/frontend/main.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import { GreetService } from "./bindings/notifications";
-import { NotificationService } from "./bindings/github.com/wailsapp/wails/v3/pkg/services/notification";
-import { Events } from "@wailsio/runtime";
-
-const resultElement = document.getElementById('result');
-const timeElement = document.getElementById('time');
-const notificationsElement = document.getElementById('notifications');
-
-const nofitications = new Map();
-
-window.doGreet = () => {
- let name = document.getElementById('name').value;
- if (!name) {
- name = 'anonymous';
- }
- GreetService.Greet(name).then((result) => {
- resultElement.innerText = result;
- }).catch((err) => {
- console.log(err);
- });
-}
-
-window.sendNotification = async () => {
- const granted = await NotificationService.CheckNotificationAuthorization();
- if (granted) {
- await NotificationService.SendNotification("some-uuid-fronted", "Frontend Notificaiton", "", "Notificaiton sent through JS!");
- }
-}
-
-window.sendComplexNotification = async () => {
- const granted = await NotificationService.CheckNotificationAuthorization();
- if (granted) {
- await NotificationService.RegisterNotificationCategory({
- id: "FRONTEND_NOTIF",
- actions: [
- { id: "VIEW_ACTION", title: "View" },
- { id: "MARK_READ_ACTION", title: "Mark as Read" },
- { id: "DELETE_ACTION", title: "Delete", destructive: true },
- ],
- hasReplyField: true,
- replyButtonTitle: "Reply",
- replyPlaceholder: "Reply to frontend...",
- });
-
- await NotificationService.SendNotificationWithActions({
- id: "some-uuid-complex",
- title: "Complex Frontend Notification",
- subtitle: "From: Jane Doe",
- body: "Is it rainging today where you are?",
- categoryId: "FRONTEND_NOTIF",
- data: {
- messageId: "msg-456",
- senderId: "user-456",
- timestamp: Date.now(),
- }
- });
- }
-}
-
-Events.On('time', (time) => {
- timeElement.innerText = time.data;
-});
-
-Events.On("notification", (data) => {
- nofitications.set(data.identifier, data);
- notificationsElement.innerText = Array.from(nofitications.values()).map(notification => JSON.stringify(notification)).join(", ");
-});
\ No newline at end of file
diff --git a/v3/examples/notifications/frontend/package.json b/v3/examples/notifications/frontend/package.json
deleted file mode 100644
index 9ae87549e..000000000
--- a/v3/examples/notifications/frontend/package.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "name": "frontend",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build:dev": "vite build --minify false --mode development",
- "build": "vite build --mode production",
- "preview": "vite preview"
- },
- "devDependencies": {
- "vite": "^5.0.0",
- "@wailsio/runtime": "latest"
- }
-}
\ No newline at end of file
diff --git a/v3/examples/notifications/frontend/public/Inter-Medium.ttf b/v3/examples/notifications/frontend/public/Inter-Medium.ttf
deleted file mode 100644
index a01f3777a..000000000
Binary files a/v3/examples/notifications/frontend/public/Inter-Medium.ttf and /dev/null differ
diff --git a/v3/examples/notifications/frontend/public/javascript.svg b/v3/examples/notifications/frontend/public/javascript.svg
deleted file mode 100644
index f9abb2b72..000000000
--- a/v3/examples/notifications/frontend/public/javascript.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/v3/examples/notifications/frontend/public/style.css b/v3/examples/notifications/frontend/public/style.css
deleted file mode 100644
index 127799eda..000000000
--- a/v3/examples/notifications/frontend/public/style.css
+++ /dev/null
@@ -1,160 +0,0 @@
-:root {
- font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
- "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
- sans-serif;
- font-size: 16px;
- line-height: 24px;
- font-weight: 400;
- color-scheme: light dark;
- color: rgba(255, 255, 255, 0.87);
- background-color: rgba(27, 38, 54, 1);
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- -webkit-text-size-adjust: 100%;
-}
-
-* {
- user-select: none;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
-}
-
-@font-face {
- font-family: "Inter";
- font-style: normal;
- font-weight: 400;
- src: local(""),
- url("./Inter-Medium.ttf") format("truetype");
-}
-
-h3 {
- font-size: 3em;
- line-height: 1.1;
-}
-
-a {
- font-weight: 500;
- color: #646cff;
- text-decoration: inherit;
-}
-
-a:hover {
- color: #535bf2;
-}
-
-button {
- /* width: 60px; */
- height: 30px;
- line-height: 30px;
- border-radius: 3px;
- border: none;
- margin: 0 0 0 20px;
- padding: 0 8px;
- cursor: pointer;
-}
-
-.result {
- height: 20px;
- line-height: 20px;
-}
-
-body {
- margin: 0;
- display: flex;
- place-items: center;
- place-content: center;
- min-width: 320px;
- min-height: 100vh;
-}
-
-.container {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
-}
-
-h1 {
- font-size: 3.2em;
- line-height: 1.1;
-}
-
-#app {
- max-width: 1280px;
- margin: 0 auto;
- padding: 2rem;
- text-align: center;
-}
-
-.logo {
- height: 6em;
- padding: 1.5em;
- will-change: filter;
-}
-
-.logo:hover {
- filter: drop-shadow(0 0 2em #e80000aa);
-}
-
-.logo.vanilla:hover {
- filter: drop-shadow(0 0 2em #f7df1eaa);
-}
-
-.result {
- height: 20px;
- line-height: 20px;
- margin: 1.5rem auto;
- text-align: center;
-}
-
-.footer {
- margin-top: 1rem;
- align-content: center;
- text-align: center;
-}
-
-@media (prefers-color-scheme: light) {
- :root {
- color: #213547;
- background-color: #ffffff;
- }
-
- a:hover {
- color: #747bff;
- }
-
- button {
- background-color: #f9f9f9;
- }
-}
-
-
-.input-box .btn:hover {
- background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%);
- color: #333333;
-}
-
-.input-box .input {
- border: none;
- border-radius: 3px;
- outline: none;
- height: 30px;
- line-height: 30px;
- padding: 0 10px;
- color: black;
- background-color: rgba(240, 240, 240, 1);
- -webkit-font-smoothing: antialiased;
-}
-
-.input-box .input:hover {
- border: none;
- background-color: rgba(255, 255, 255, 1);
-}
-
-.input-box .input:focus {
- border: none;
- background-color: rgba(255, 255, 255, 1);
-}
\ No newline at end of file
diff --git a/v3/examples/notifications/frontend/public/wails.png b/v3/examples/notifications/frontend/public/wails.png
deleted file mode 100644
index 8bdf42483..000000000
Binary files a/v3/examples/notifications/frontend/public/wails.png and /dev/null differ
diff --git a/v3/examples/notifications/main.go b/v3/examples/notifications/main.go
deleted file mode 100644
index 35fb7b06b..000000000
--- a/v3/examples/notifications/main.go
+++ /dev/null
@@ -1,135 +0,0 @@
-package main
-
-import (
- _ "embed"
- "fmt"
- "log"
- "time"
-
- "github.com/wailsapp/wails/v3/pkg/application"
- "github.com/wailsapp/wails/v3/pkg/events"
- "github.com/wailsapp/wails/v3/pkg/services/notification"
-)
-
-func main() {
- app := application.New(application.Options{
- Name: "Notifications Demo",
- Description: "A test of macOS notifications",
- Assets: application.AlphaAssets,
- Services: []application.Service{
- application.NewService(¬ification.NotificationService{}),
- },
- })
-
- app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
- Width: 500,
- Height: 800,
- })
-
- app.OnApplicationEvent(events.Mac.ApplicationDidFinishLaunching, func(event *application.ApplicationEvent) {
- // Request pemission to send notifications
- granted, err := application.RequestUserNotificationAuthorization()
- if err != nil {
- log.Default().Printf("WARNING: %s\n", err)
- }
-
- if granted {
- // Send notification with no actions
- err = application.SendNotification("some-uuid", "Title", "", "body!")
- if err != nil {
- log.Default().Printf("WARNING: %s\n", err)
- }
-
- err = application.RegisterNotificationCategory(application.NotificationCategory{
- ID: "MESSAGE_CATEGORY",
- Actions: []application.NotificationAction{
- {ID: "VIEW_ACTION", Title: "View"},
- {ID: "MARK_READ_ACTION", Title: "Mark as Read"},
- {ID: "DELETE_ACTION", Title: "Delete", Destructive: true},
- },
- HasReplyField: true,
- ReplyPlaceholder: "Type your reply...",
- ReplyButtonTitle: "Reply",
- })
- if err != nil {
- log.Default().Printf("WARNING: %s\n", err)
- }
-
- err = application.SendNotificationWithActions(application.NotificationOptions{
- ID: "some-other-uuid",
- Title: "New Message",
- Subtitle: "From: Jane Doe",
- Body: "Is it raining today where you are?",
- CategoryID: "MESSAGE_CATEGORY",
- Data: map[string]interface{}{
- "messageId": "msg-123",
- "senderId": "user-123",
- "timestamp": time.Now().Unix(),
- },
- })
- if err != nil {
- log.Default().Printf("WARNING: %s\n", err)
- }
- }
- })
-
- app.OnApplicationEvent(events.Mac.DidReceiveNotificationResponse, func(event *application.ApplicationEvent) {
- data := event.Context().GetData()
-
- // Parse data received
- if data != nil {
- if identifier, ok := data["identifier"].(string); ok {
- fmt.Printf("Notification identifier: %s\n", identifier)
- }
-
- if actionIdentifier, ok := data["actionIdentifier"].(string); ok {
- fmt.Printf("Action Identifier: %s\n", actionIdentifier)
- }
-
- if userText, ok := data["userText"].(string); ok {
- fmt.Printf("User replied: %s\n", userText)
- }
-
- if userInfo, ok := data["userInfo"].(map[string]interface{}); ok {
- fmt.Printf("Custom data: %+v\n", userInfo)
- }
-
- // Send notification to JS
- app.EmitEvent("notification", data)
- }
- })
-
- go func() {
- time.Sleep(time.Second * 5)
- // Sometime later check if you are still authorized
- granted, err := application.CheckNotificationAuthorization()
- if err != nil {
- log.Default().Printf("WARNING: %s\n", err)
- }
- println(granted)
-
- // Sometime later remove delivered notification by identifier
- err = application.RemoveDeliveredNotification("some-uuid")
- if err != nil {
- log.Default().Printf("WARNING: %s\n", err)
- }
- }()
-
- go func() {
- time.Sleep(time.Second * 10)
- // Sometime later remove all pending and delivered notifications
- err := application.RemoveAllPendingNotifications()
- if err != nil {
- log.Default().Printf("WARNING: %s\n", err)
- }
- err = application.RemoveAllDeliveredNotifications()
- if err != nil {
- log.Default().Printf("WARNING: %s\n", err)
- }
- }()
-
- err := app.Run()
- if err != nil {
- log.Fatal(err)
- }
-}
diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.js
new file mode 100644
index 000000000..eb8893845
--- /dev/null
+++ b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.js
@@ -0,0 +1,25 @@
+// @ts-check
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+
+import * as Service from "./service.js";
+export {
+ Service
+};
+
+import * as $models from "./models.js";
+
+/**
+ * NotificationAction represents an action button for a notification
+ * @typedef {$models.NotificationAction} NotificationAction
+ */
+
+/**
+ * NotificationCategory groups actions for notifications
+ * @typedef {$models.NotificationCategory} NotificationCategory
+ */
+
+/**
+ * NotificationOptions contains configuration for a notification
+ * @typedef {$models.NotificationOptions} NotificationOptions
+ */
diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/models.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/models.js
new file mode 100644
index 000000000..2525e0f38
--- /dev/null
+++ b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/models.js
@@ -0,0 +1,37 @@
+// @ts-check
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-ignore: Unused imports
+import {Create as $Create} from "@wailsio/runtime";
+
+/**
+ * NotificationAction represents an action button for a notification
+ * @typedef {Object} NotificationAction
+ * @property {string} id
+ * @property {string} title
+ * @property {boolean} [destructive]
+ * @property {boolean} [authenticationRequired]
+ */
+
+/**
+ * NotificationCategory groups actions for notifications
+ * @typedef {Object} NotificationCategory
+ * @property {string} id
+ * @property {NotificationAction[]} actions
+ * @property {boolean} [hasReplyField]
+ * @property {string} [replyPlaceholder]
+ * @property {string} [replyButtonTitle]
+ */
+
+/**
+ * NotificationOptions contains configuration for a notification
+ * @typedef {Object} NotificationOptions
+ * @property {string} id
+ * @property {string} title
+ * @property {string} [subtitle]
+ * @property {string} body
+ * @property {string} [categoryId]
+ * @property {{ [_: string]: any }} [data]
+ */
diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/service.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/service.js
new file mode 100644
index 000000000..5c91a1c77
--- /dev/null
+++ b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/service.js
@@ -0,0 +1,98 @@
+// @ts-check
+// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
+// This file is automatically generated. DO NOT EDIT
+
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-ignore: Unused imports
+import {Call as $Call, Create as $Create} from "@wailsio/runtime";
+
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-ignore: Unused imports
+import * as $models from "./models.js";
+
+/**
+ * CheckNotificationAuthorization checks current permission status
+ * @returns {Promise & { cancel(): void }}
+ */
+export function CheckNotificationAuthorization() {
+ let $resultPromise = /** @type {any} */($Call.ByID(2789931702));
+ return $resultPromise;
+}
+
+/**
+ * RegisterNotificationCategory registers a category with actions and optional reply field
+ * @param {$models.NotificationCategory} category
+ * @returns {Promise & { cancel(): void }}
+ */
+export function RegisterNotificationCategory(category) {
+ let $resultPromise = /** @type {any} */($Call.ByID(2679064664, category));
+ return $resultPromise;
+}
+
+/**
+ * @returns {Promise & { cancel(): void }}
+ */
+export function RemoveAllDeliveredNotifications() {
+ let $resultPromise = /** @type {any} */($Call.ByID(384520397));
+ return $resultPromise;
+}
+
+/**
+ * RemoveAllPendingNotifications removes all pending notifications
+ * @returns {Promise & { cancel(): void }}
+ */
+export function RemoveAllPendingNotifications() {
+ let $resultPromise = /** @type {any} */($Call.ByID(1423986276));
+ return $resultPromise;
+}
+
+/**
+ * @param {string} identifier
+ * @returns {Promise & { cancel(): void }}
+ */
+export function RemoveDeliveredNotification(identifier) {
+ let $resultPromise = /** @type {any} */($Call.ByID(149440045, identifier));
+ return $resultPromise;
+}
+
+/**
+ * RemovePendingNotification removes a specific pending notification
+ * @param {string} identifier
+ * @returns {Promise & { cancel(): void }}
+ */
+export function RemovePendingNotification(identifier) {
+ let $resultPromise = /** @type {any} */($Call.ByID(3872412470, identifier));
+ return $resultPromise;
+}
+
+/**
+ * RequestUserNotificationAuthorization requests permission for notifications.
+ * @returns {Promise & { cancel(): void }}
+ */
+export function RequestUserNotificationAuthorization() {
+ let $resultPromise = /** @type {any} */($Call.ByID(3412125712));
+ return $resultPromise;
+}
+
+/**
+ * SendNotification sends a notification with the given identifier, title, subtitle, and body.
+ * @param {string} identifier
+ * @param {string} title
+ * @param {string} subtitle
+ * @param {string} body
+ * @returns {Promise & { cancel(): void }}
+ */
+export function SendNotification(identifier, title, subtitle, body) {
+ let $resultPromise = /** @type {any} */($Call.ByID(2246903123, identifier, title, subtitle, body));
+ return $resultPromise;
+}
+
+/**
+ * SendNotificationWithActions sends a notification with the specified actions
+ * @param {$models.NotificationOptions} options
+ * @returns {Promise & { cancel(): void }}
+ */
+export function SendNotificationWithActions(options) {
+ let $resultPromise = /** @type {any} */($Call.ByID(1615199806, options));
+ return $resultPromise;
+}
diff --git a/v3/examples/services/assets/index.html b/v3/examples/services/assets/index.html
index 67746fdec..24a372593 100644
--- a/v3/examples/services/assets/index.html
+++ b/v3/examples/services/assets/index.html
@@ -10,6 +10,13 @@
import * as kvstore from './bindings/github.com/wailsapp/wails/v3/pkg/services/kvstore/keyvaluestore.js';
import {Debug, Info, Warning, Error} from './bindings/github.com/wailsapp/wails/v3/pkg/services/log/loggerservice.js';
import * as hash from './bindings/github.com/wailsapp/wails/v3/examples/services/hashes/service.js';
+ import * as notifications from "./bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/service.js"
+
+ notifications.RequestUserNotificationAuthorization().then((granted) => {
+ if (granted) {
+ notifications.SendNotification("some-uuid-fronted", "Frontend Notificaiton", "", "Notificaiton sent through JS!");
+ }
+ });
function runHash() {
let hashstring = document.getElementById("hashstring").value;
diff --git a/v3/examples/services/main.go b/v3/examples/services/main.go
index a4ebb6bf4..6bc020c8a 100644
--- a/v3/examples/services/main.go
+++ b/v3/examples/services/main.go
@@ -2,16 +2,18 @@ package main
import (
"embed"
+ "log/slog"
+ "os"
+ "path/filepath"
+ "runtime"
+
"github.com/wailsapp/wails/v3/examples/services/hashes"
"github.com/wailsapp/wails/v3/pkg/application"
"github.com/wailsapp/wails/v3/pkg/services/fileserver"
"github.com/wailsapp/wails/v3/pkg/services/kvstore"
"github.com/wailsapp/wails/v3/pkg/services/log"
+ "github.com/wailsapp/wails/v3/pkg/services/notifications"
"github.com/wailsapp/wails/v3/pkg/services/sqlite"
- "log/slog"
- "os"
- "path/filepath"
- "runtime"
)
//go:embed assets/*
@@ -48,6 +50,7 @@ func main() {
}), application.ServiceOptions{
Route: "/files",
}),
+ application.NewService(notifications.New()),
},
Assets: application.AssetOptions{
Handler: application.BundledAssetFileServer(assets),
diff --git a/v3/pkg/application/notifications_darwin.go b/v3/pkg/application/notifications_darwin.go
deleted file mode 100644
index e04075238..000000000
--- a/v3/pkg/application/notifications_darwin.go
+++ /dev/null
@@ -1,177 +0,0 @@
-//go:build darwin
-
-package application
-
-/*
-#cgo CFLAGS: -mmacosx-version-min=10.14 -x objective-c
-#cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.14 -framework UserNotifications
-#import "notifications_darwin.h"
-*/
-import "C"
-import (
- "encoding/json"
- "fmt"
- "unsafe"
-)
-
-// NotificationAction represents a button in a notification
-type NotificationAction struct {
- ID string `json:"id"`
- Title string `json:"title"`
- Destructive bool `json:"destructive,omitempty"`
- AuthenticationRequired bool `json:"authenticationRequired,omitempty"`
-}
-
-// NotificationCategory groups actions for notifications
-type NotificationCategory struct {
- ID string `json:"id"`
- Actions []NotificationAction `json:"actions"`
- HasReplyField bool `json:"hasReplyField,omitempty"`
- ReplyPlaceholder string `json:"replyPlaceholder,omitempty"`
- ReplyButtonTitle string `json:"replyButtonTitle,omitempty"`
-}
-
-// NotificationOptions contains configuration for a notification
-type NotificationOptions struct {
- ID string `json:"id"`
- Title string `json:"title"`
- Subtitle string `json:"subtitle,omitempty"`
- Body string `json:"body"`
- CategoryID string `json:"categoryId,omitempty"`
- Data map[string]interface{} `json:"data,omitempty"`
-}
-
-// Check if the app has a valid bundle identifier
-func CheckBundleIdentifier() bool {
- return bool(C.checkBundleIdentifier())
-}
-
-// RequestUserNotificationAuthorization requests permission for notifications.
-func RequestUserNotificationAuthorization() (bool, error) {
- if !CheckBundleIdentifier() {
- return false, fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
- }
- result := C.requestUserNotificationAuthorization(nil)
- return result == true, nil
-}
-
-// CheckNotificationAuthorization checks current permission status
-func CheckNotificationAuthorization() (bool, error) {
- if !CheckBundleIdentifier() {
- return false, fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
- }
- return bool(C.checkNotificationAuthorization()), nil
-}
-
-// SendNotification sends a notification with the given identifier, title, subtitle, and body.
-func SendNotification(identifier, title, subtitle, body string) error {
- if !CheckBundleIdentifier() {
- return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
- }
- cIdentifier := C.CString(identifier)
- cTitle := C.CString(title)
- cSubtitle := C.CString(subtitle)
- cBody := C.CString(body)
- defer C.free(unsafe.Pointer(cIdentifier))
- defer C.free(unsafe.Pointer(cTitle))
- defer C.free(unsafe.Pointer(cSubtitle))
- defer C.free(unsafe.Pointer(cBody))
-
- C.sendNotification(cIdentifier, cTitle, cSubtitle, cBody, nil)
- return nil
-}
-
-// SendNotificationWithActions sends a notification with the specified actions
-func SendNotificationWithActions(options NotificationOptions) error {
- if !CheckBundleIdentifier() {
- return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
- }
- cIdentifier := C.CString(options.ID)
- cTitle := C.CString(options.Title)
- cSubtitle := C.CString(options.Subtitle)
- cBody := C.CString(options.Body)
- cCategoryID := C.CString(options.CategoryID)
- defer C.free(unsafe.Pointer(cIdentifier))
- defer C.free(unsafe.Pointer(cTitle))
- defer C.free(unsafe.Pointer(cSubtitle))
- defer C.free(unsafe.Pointer(cBody))
- defer C.free(unsafe.Pointer(cCategoryID))
-
- var cActionsJSON *C.char
- if options.Data != nil {
- jsonData, err := json.Marshal(options.Data)
- if err == nil {
- cActionsJSON = C.CString(string(jsonData))
- defer C.free(unsafe.Pointer(cActionsJSON))
- }
- }
-
- C.sendNotificationWithActions(cIdentifier, cTitle, cSubtitle, cBody, cCategoryID, cActionsJSON, nil)
- return nil
-}
-
-// RegisterNotificationCategory registers a category with actions and optional reply field
-func RegisterNotificationCategory(category NotificationCategory) error {
- if !CheckBundleIdentifier() {
- return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
- }
- cCategoryID := C.CString(category.ID)
- defer C.free(unsafe.Pointer(cCategoryID))
-
- actionsJSON, err := json.Marshal(category.Actions)
- if err != nil {
- return err
- }
- cActionsJSON := C.CString(string(actionsJSON))
- defer C.free(unsafe.Pointer(cActionsJSON))
-
- var cReplyPlaceholder, cReplyButtonTitle *C.char
- if category.HasReplyField {
- cReplyPlaceholder = C.CString(category.ReplyPlaceholder)
- cReplyButtonTitle = C.CString(category.ReplyButtonTitle)
- defer C.free(unsafe.Pointer(cReplyPlaceholder))
- defer C.free(unsafe.Pointer(cReplyButtonTitle))
- }
-
- C.registerNotificationCategory(cCategoryID, cActionsJSON, C.bool(category.HasReplyField),
- cReplyPlaceholder, cReplyButtonTitle)
- return nil
-}
-
-// RemoveAllPendingNotifications removes all pending notifications
-func RemoveAllPendingNotifications() error {
- if !CheckBundleIdentifier() {
- return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
- }
- C.removeAllPendingNotifications()
- return nil
-}
-
-// RemovePendingNotification removes a specific pending notification
-func RemovePendingNotification(identifier string) error {
- if !CheckBundleIdentifier() {
- return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
- }
- cIdentifier := C.CString(identifier)
- defer C.free(unsafe.Pointer(cIdentifier))
- C.removePendingNotification(cIdentifier)
- return nil
-}
-
-func RemoveAllDeliveredNotifications() error {
- if !CheckBundleIdentifier() {
- return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
- }
- C.removeAllDeliveredNotifications()
- return nil
-}
-
-func RemoveDeliveredNotification(identifier string) error {
- if !CheckBundleIdentifier() {
- return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
- }
- cIdentifier := C.CString(identifier)
- defer C.free(unsafe.Pointer(cIdentifier))
- C.removeDeliveredNotification(cIdentifier)
- return nil
-}
diff --git a/v3/pkg/services/notification/notification.go b/v3/pkg/services/notifications/notifications.go
similarity index 83%
rename from v3/pkg/services/notification/notification.go
rename to v3/pkg/services/notifications/notifications.go
index 987e4d438..8f700daf5 100644
--- a/v3/pkg/services/notification/notification.go
+++ b/v3/pkg/services/notifications/notifications.go
@@ -1,11 +1,11 @@
//go:build darwin
-package notification
+package notifications
/*
#cgo CFLAGS: -mmacosx-version-min=10.14 -x objective-c
#cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.14 -framework UserNotifications
-#import "../../application/notifications_darwin.h"
+#import "./notifications_darwin.h"
*/
import "C"
import (
@@ -17,11 +17,11 @@ import (
"github.com/wailsapp/wails/v3/pkg/application"
)
-type NotificationService struct {
+type Service struct {
}
// NotificationAction represents an action button for a notification
-type NotificationAction struct {
+type NotificationAction = struct {
ID string `json:"id"`
Title string `json:"title"`
Destructive bool `json:"destructive,omitempty"`
@@ -29,7 +29,7 @@ type NotificationAction struct {
}
// NotificationCategory groups actions for notifications
-type NotificationCategory struct {
+type NotificationCategory = struct {
ID string `json:"id"`
Actions []NotificationAction `json:"actions"`
HasReplyField bool `json:"hasReplyField,omitempty"`
@@ -38,7 +38,7 @@ type NotificationCategory struct {
}
// NotificationOptions contains configuration for a notification
-type NotificationOptions struct {
+type NotificationOptions = struct {
ID string `json:"id"`
Title string `json:"title"`
Subtitle string `json:"subtitle,omitempty"`
@@ -47,17 +47,21 @@ type NotificationOptions struct {
Data map[string]interface{} `json:"data,omitempty"`
}
+func New() *Service {
+ return &Service{}
+}
+
func CheckBundleIdentifier() bool {
return bool(C.checkBundleIdentifier())
}
// ServiceName returns the name of the service
-func (ns *NotificationService) ServiceName() string {
+func (ns *Service) ServiceName() string {
return "github.com/wailsapp/wails/v3/services/notifications"
}
// ServiceStartup is called when the service is loaded
-func (ns *NotificationService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
+func (ns *Service) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
if !CheckBundleIdentifier() {
return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
}
@@ -65,12 +69,12 @@ func (ns *NotificationService) ServiceStartup(ctx context.Context, options appli
}
// ServiceShutdown is called when the service is unloaded
-func (ns *NotificationService) ServiceShutdown() error {
+func (ns *Service) ServiceShutdown() error {
return nil
}
// RequestUserNotificationAuthorization requests permission for notifications.
-func (ns *NotificationService) RequestUserNotificationAuthorization() (bool, error) {
+func (ns *Service) RequestUserNotificationAuthorization() (bool, error) {
if !CheckBundleIdentifier() {
return false, fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
}
@@ -79,7 +83,7 @@ func (ns *NotificationService) RequestUserNotificationAuthorization() (bool, err
}
// CheckNotificationAuthorization checks current permission status
-func (ns *NotificationService) CheckNotificationAuthorization() (bool, error) {
+func (ns *Service) CheckNotificationAuthorization() (bool, error) {
if !CheckBundleIdentifier() {
return false, fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
}
@@ -87,7 +91,7 @@ func (ns *NotificationService) CheckNotificationAuthorization() (bool, error) {
}
// SendNotification sends a notification with the given identifier, title, subtitle, and body.
-func (ns *NotificationService) SendNotification(identifier, title, subtitle, body string) error {
+func (ns *Service) SendNotification(identifier, title, subtitle, body string) error {
if !CheckBundleIdentifier() {
return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
}
@@ -105,7 +109,7 @@ func (ns *NotificationService) SendNotification(identifier, title, subtitle, bod
}
// SendNotificationWithActions sends a notification with the specified actions
-func (ns *NotificationService) SendNotificationWithActions(options NotificationOptions) error {
+func (ns *Service) SendNotificationWithActions(options NotificationOptions) error {
if !CheckBundleIdentifier() {
return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
}
@@ -134,7 +138,7 @@ func (ns *NotificationService) SendNotificationWithActions(options NotificationO
}
// RegisterNotificationCategory registers a category with actions and optional reply field
-func (ns *NotificationService) RegisterNotificationCategory(category NotificationCategory) error {
+func (ns *Service) RegisterNotificationCategory(category NotificationCategory) error {
if !CheckBundleIdentifier() {
return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
}
@@ -162,7 +166,7 @@ func (ns *NotificationService) RegisterNotificationCategory(category Notificatio
}
// RemoveAllPendingNotifications removes all pending notifications
-func (ns *NotificationService) RemoveAllPendingNotifications() error {
+func (ns *Service) RemoveAllPendingNotifications() error {
if !CheckBundleIdentifier() {
return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
}
@@ -171,7 +175,7 @@ func (ns *NotificationService) RemoveAllPendingNotifications() error {
}
// RemovePendingNotification removes a specific pending notification
-func (ns *NotificationService) RemovePendingNotification(identifier string) error {
+func (ns *Service) RemovePendingNotification(identifier string) error {
if !CheckBundleIdentifier() {
return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
}
@@ -181,7 +185,7 @@ func (ns *NotificationService) RemovePendingNotification(identifier string) erro
return nil
}
-func (ns *NotificationService) RemoveAllDeliveredNotifications() error {
+func (ns *Service) RemoveAllDeliveredNotifications() error {
if !CheckBundleIdentifier() {
return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
}
@@ -189,7 +193,7 @@ func (ns *NotificationService) RemoveAllDeliveredNotifications() error {
return nil
}
-func (ns *NotificationService) RemoveDeliveredNotification(identifier string) error {
+func (ns *Service) RemoveDeliveredNotification(identifier string) error {
if !CheckBundleIdentifier() {
return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier")
}
diff --git a/v3/pkg/application/notifications_darwin.h b/v3/pkg/services/notifications/notifications_darwin.h
similarity index 100%
rename from v3/pkg/application/notifications_darwin.h
rename to v3/pkg/services/notifications/notifications_darwin.h
diff --git a/v3/pkg/application/notifications_darwin.m b/v3/pkg/services/notifications/notifications_darwin.m
similarity index 99%
rename from v3/pkg/application/notifications_darwin.m
rename to v3/pkg/services/notifications/notifications_darwin.m
index 7c0a1cade..f4e9b1404 100644
--- a/v3/pkg/application/notifications_darwin.m
+++ b/v3/pkg/services/notifications/notifications_darwin.m
@@ -1,7 +1,7 @@
#import "notifications_darwin.h"
#import
#import
-#import "../events/events_darwin.h"
+#import "../../events/events_darwin.h"
extern bool hasListeners(unsigned int);
extern void processApplicationEvent(unsigned int, void* data);