Notifikasi
Tampilkan notifikasi sistem native dengan tombol tindakan dan input teks
Pendahuluan
Wails menyediakan sistem notifikasi lintas platform yang lengkap untuk aplikasi desktop. Layanan ini memungkinkan Anda menampilkan notifikasi sistem native, dengan dukungan untuk:
- Notifikasi dasar dengan judul, subjudul, dan isi
- Notifikasi interaktif dengan tombol tindakan dan balasan teks
- Kategori notifikasi yang dapat digunakan kembali untuk tindakan
- Suara khusus (default, senyap, atau bernama)
- Lampiran (gambar di setiap platform; audio/video di macOS)
- Pengelompokan notifikasi terkait berdasarkan
ThreadID - Prioritas melalui
InterruptionLevel(passive/active/timeSensitive/critical) - Pengiriman terjadwal (native di macOS; timer dalam proses di Windows + Linux)
- Pembaruan notifikasi yang sedang aktif berdasarkan ID
Setiap kolom opsional baru mengalami degradasi secara wajar ketika suatu platform tidak dapat mendukungnya; lihat Pertimbangan Platform untuk matriks dukungan setiap fitur.
Penggunaan Dasar
Membuat Layanan
Pertama, inisialisasi layanan notifikasi:
import "github.com/wailsapp/wails/v3/pkg/application"
import "github.com/wailsapp/wails/v3/pkg/services/notifications"
// Create a new notification service
notifier := notifications.New()
//Register the service with the application
app := application.New(application.Options{
Services: []application.Service{
application.NewService(notifier),
},
})Otorisasi Notifikasi
Notifikasi di macOS memerlukan otorisasi pengguna. Minta dan periksa otorisasi:
authorized, err := notifier.CheckNotificationAuthorization()
if err != nil {
// Handle authorization error
}
if authorized {
// Send notifications
} else {
// Request authorization
authorized, err = notifier.RequestNotificationAuthorization()
}Di Windows dan Linux, ini selalu mengembalikan true.
Jenis Notifikasi
Notifikasi Dasar
Kirim notifikasi dasar kepada pengguna dengan ID unik, judul, subjudul opsional (macOS dan Linux), serta teks isi:
notifier.SendNotification(notifications.NotificationOptions{
ID: "unique-id",
Title: "New Calendar Invite",
Subtitle: "From: Jane Doe", // Optional
Body: "Tap to view the event",
})
Notifikasi Interaktif
Kirim notifikasi dengan tombol tindakan dan input teks. Kategori notifikasi harus didaftarkan terlebih dahulu untuk menggunakan notifikasi ini:
// Define a unique category id
categoryID := "unique-category-id"
// Define a category with actions
category := notifications.NotificationCategory{
ID: categoryID,
Actions: []notifications.NotificationAction{
{
ID: "OPEN",
Title: "Open",
},
{
ID: "ARCHIVE",
Title: "Archive",
Destructive: true, /* macOS-specific */
},
},
HasReplyField: true,
ReplyPlaceholder: "message...",
ReplyButtonTitle: "Reply",
}
// Register the category
notifier.RegisterNotificationCategory(category)
// Send an interactive notification with the actions registered in the provided category
notifier.SendNotificationWithActions(notifications.NotificationOptions{
ID: "unique-id",
Title: "New Message",
Subtitle: "From: Jane Doe",
Body: "Are you able to make it?",
CategoryID: categoryID,
})Respons Notifikasi
Proses interaksi pengguna dengan notifikasi:
notifier.OnNotificationResponse(func(result notifications.NotificationResult) {
response := result.Response
fmt.Printf("Notification %s was actioned with: %s\n", response.ID, response.ActionIdentifier)
if response.ActionIdentifier == "TEXT_REPLY" {
fmt.Printf("User replied: %s\n", response.UserText)
}
if data, ok := response.UserInfo["sender"].(string); ok {
fmt.Printf("Original sender: %s\n", data)
}
// Emit an event to the frontend
app.Event.Emit("notification", result.Response)
})Penyesuaian Notifikasi
Metadata Khusus
Notifikasi dasar dan interaktif dapat menyertakan data khusus:
notifier.SendNotification(notifications.NotificationOptions{
ID: "unique-id",
Title: "New Calendar Invite",
Subtitle: "From: Jane Doe", // Optional
Body: "Tap to view the event",
Data: map[string]interface{}{
"sender": "jane.doe@example.com",
"timestamp": "2025-03-10T15:30:00Z",
}
})Suara Khusus
Gunakan Sound untuk mengontrol audio yang diputar saat notifikasi dikirimkan. Jika dibiarkan nil, suara default platform akan diputar; atur Silent: true untuk menonaktifkan suara; atur Name untuk memutar suara bernama/yang disertakan dalam bundel.
// Silent
notifier.SendNotification(notifications.NotificationOptions{
ID: "silent-id",
Title: "Background sync complete",
Sound: ¬ifications.NotificationSound{Silent: true},
})
// Named sound
notifier.SendNotification(notifications.NotificationOptions{
ID: "named-id",
Title: "New message",
Body: "Tap to read",
Sound: ¬ifications.NotificationSound{Name: "Ping"},
})Cara Name ditentukan di setiap platform:
- macOS —
Namediteruskan ke[UNNotificationSound soundNamed:]; berkas audio harus berada di bawahLibrary/Soundsdalam bundel aplikasi Anda. - Windows — jika
Namesudah diawali denganms-winsoundevent:ataums-appx:, nilainya digunakan apa adanya; jika tidak, nilainya dibungkus dalamms-winsoundevent:agar dapat digunakan sebagai nama peristiwa toast bawaan (lihat dokumentasi skema<audio>toast Microsoft). - Linux — diteruskan sebagai petunjuk
sound-namefreedesktop; pemutarannya bergantung pada daemon notifikasi dan tema suara yang aktif.
Lampiran
Attachments menambahkan berkas media bersama notifikasi. macOS mendukung beberapa lampiran dari jenis media apa pun; Windows dan Linux mendukung lampiran pertama yang berjenis gambar.
notifier.SendNotification(notifications.NotificationOptions{
ID: "image-id",
Title: "Photo uploaded",
Body: "Tap to view",
Attachments: []notifications.NotificationAttachment{
{
ID: "preview",
Path: "/absolute/path/to/image.png",
// Type hint:
// macOS: UTI like "public.png" / "public.audio" (often inferred)
// Windows: "hero" | "appLogoOverride" | "inline" (default "inline")
// Linux: ignored
Type: "inline",
},
},
})Path harus berupa jalur absolut sistem berkas. macOS juga menerima URL file://.
Melampirkan berkas yang disertakan bersama aplikasi Anda
OS membaca lampiran dari disk saat notifikasi dikirimkan, sehingga Path harus merujuk ke berkas nyata di komputer pengguna akhir. Untuk aset yang Anda sertakan dalam bundel aplikasi (ikon atau gambar yang disematkan dengan go:embed), tidak ada jalur absolut tetap yang dapat Anda tuliskan langsung dalam kode karena berkas tersebut berada di dalam biner, bukan di lokasi disk yang diketahui. Tulis berkas tersebut satu kali ke direktori yang dapat ditulisi saat aplikasi dimulai, lalu teruskan jalurnya:
import (
_ "embed"
"os"
"path/filepath"
)
//go:embed assets/preview.png
var previewPNG []byte
// Materialise the embedded asset to a stable path the OS can read.
previewPath := filepath.Join(os.TempDir(), "myapp-preview.png")
if err := os.WriteFile(previewPath, previewPNG, 0o644); err != nil {
// handle error
}
notifier.SendNotification(notifications.NotificationOptions{
ID: "image-id",
Title: "Photo uploaded",
Body: "Tap to view",
Attachments: []notifications.NotificationAttachment{
{ID: "preview", Path: previewPath, Type: "inline"},
},
})Berkas yang disediakan pengguna atau diunduh sudah memiliki jalur nyata di disk, sehingga Anda dapat meneruskannya langsung ke Path tanpa langkah ini. Dukungan untuk meneruskan byte lampiran dalam memori mungkin ditambahkan dalam rilis mendatang.
Utas dan Pengelompokan
ThreadID mengelompokkan notifikasi terkait agar OS dapat menciutkannya di Notification Center / Action Center.
notifier.SendNotification(notifications.NotificationOptions{
ID: "msg-42",
Title: "Jane Doe",
Body: "Are you free for lunch?",
ThreadID: "chat:jane.doe",
})Tingkat Interupsi
InterruptionLevel mengontrol prioritas notifikasi. Gunakan salah satu konstanta yang diekspor:
notifier.SendNotification(notifications.NotificationOptions{
ID: "alert-id",
Title: "Server down",
Body: "Investigate immediately",
InterruptionLevel: notifications.InterruptionLevelTimeSensitive,
})| Konstanta | Nilai | Arti |
|---|---|---|
InterruptionLevelPassive |
"passive" |
Pengiriman senyap; tidak akan menyalakan layar atau memutar suara default |
InterruptionLevelActive |
"active" |
Tingkat default |
InterruptionLevelTimeSensitive |
"timeSensitive" |
Menerobos mode Focus / Do Not Disturb jika diizinkan |
InterruptionLevelCritical |
"critical" |
Melewati Fokus dan dering; macOS memerlukan hak Critical Alert (tanpanya, fungsi ini akan diturunkan secara diam-diam) |
Pemetaan per platform:
- macOS — menetapkan
UNNotificationContent.interruptionLevel.criticalmemerlukan macOS 12+ dan hak Critical Alert. - Windows — dipetakan ke atribut toast
<toast scenario="...">. - Linux — dipetakan ke petunjuk freedesktop
urgency.
Pengiriman Terjadwal
Schedule menunda pengiriman. Tetapkan tepat salah satu dari DelaySeconds (detik dari sekarang) atau At (detik Unix, UTC).
// Deliver in 60 seconds
notifier.SendNotification(notifications.NotificationOptions{
ID: "reminder-id",
Title: "Stand up and stretch",
Schedule: ¬ifications.NotificationSchedule{DelaySeconds: 60},
})
// Deliver at an absolute time
notifier.SendNotification(notifications.NotificationOptions{
ID: "alarm-id",
Title: "Meeting in 5 minutes",
Schedule: ¬ifications.NotificationSchedule{At: time.Now().Add(time.Hour).Unix()},
})Memperbarui Notifikasi
UpdateNotification mengganti notifikasi yang sedang diproses dengan ID yang sama:
notifier.UpdateNotification(notifications.NotificationOptions{
ID: "download-id",
Title: "Download complete",
Body: "report.pdf is ready",
})Perilaku per platform:
- macOS —
UNUserNotificationCentersecara otomatis menghapus duplikasi berdasarkan pengidentifikasi, sehingga notifikasi yang ada diperbarui langsung. - Linux — menggunakan parameter D-Bus
replaces_iduntuk mengganti notifikasi sebelumnya. - Windows — saat ini mengirimkannya kembali sebagai notifikasi baru. Penggantian langsung yang sebenarnya memerlukan dukungan
wintoastupstream untuktag/group.
Pertimbangan Platform
Di macOS, notifikasi:
- Memerlukan otorisasi pengguna
- Mengharuskan aplikasi dikemas dan ditandatangani (dinotarisasi untuk distribusi)
- Menggunakan tampilan notifikasi standar sistem
- Mendukung
Subtitle - Mendukung masukan teks pengguna (balasan)
- Mendukung opsi tindakan
Destructive - Mendukung beberapa
Attachmentsdari semua jenis media (gambar, audio, video) - Mendukung
ThreadIDuntuk pengelompokan di Notification Center - Mendukung semua nilai
InterruptionLevel(criticalmemerlukan hak Critical Alert) - Mendukung pengiriman terjadwal native yang tetap ada setelah aplikasi dimulai ulang
- Secara otomatis menghapus duplikasi panggilan
UpdateNotificationberdasarkanID - Menangani mode gelap/terang secara otomatis
Di Windows, notifikasi:
- Menggunakan gaya toast sistem Windows melalui backend
wintoast - Menyesuaikan dengan pengaturan tema Windows
- Mendukung masukan teks pengguna (balasan)
- Mendukung layar DPI tinggi
- Tidak mendukung
Subtitle - Mendukung satu
Attachmentgambar dengan petunjuk penempatanhero,appLogoOverride, atauinline(defaultinline) - Mendukung
ThreadIDuntuk pengelompokan di Action Center - Mendukung
InterruptionLevelmelalui atribut toastscenario - Mendukung pengiriman terjadwal melalui timer dalam proses — notifikasi terjadwal akan hilang jika aplikasi ditutup sebelum pengiriman
UpdateNotificationsaat ini mengirimkannya kembali sebagai notifikasi baru (penggantian langsung yang sebenarnya menunggu dukunganwintoastupstream untuktag/group)
Di Linux, notifikasi menggunakan antarmuka D-Bus org.freedesktop.Notifications. Daemon notifikasi yang kompatibel harus berjalan agar notifikasi dapat berfungsi.
Di Linux, notifikasi:
- Mengikuti tema lingkungan desktop
- Diposisikan sesuai aturan lingkungan desktop
- Mendukung
Subtitle(digabungkan ke dalam isi untuk daemon yang tidak merendernya secara terpisah) - Tidak mendukung masukan teks pengguna (bukan bagian dari spesifikasi freedesktop)
- Mendukung satu
Attachmentgambar melalui petunjukimage-path - Mendukung
ThreadID(ditangani oleh daemon jika didukung) Sound.Namediteruskan sebagai hintsound-name; pemutarannya bergantung pada daemon dan tema suara yang aktif- Memetakan
InterruptionLevelke hint freedesktopurgency - Mendukung pengiriman terjadwal melalui timer dalam proses — notifikasi terjadwal akan hilang jika aplikasi ditutup sebelum dikirim
UpdateNotificationmenggunakan parameter D-Busreplaces_iduntuk mengganti notifikasi sebelumnya di tempat
Praktik Terbaik
- Periksa dan minta otorisasi:
- macOS memerlukan otorisasi pengguna
- Berikan notifikasi yang jelas dan ringkas:
- Gunakan judul, subtitel, teks, dan judul tindakan yang deskriptif
- Tangani respons notifikasi dengan tepat:
- Periksa apakah ada kesalahan dalam respons notifikasi
- Berikan umpan balik atas tindakan pengguna
- Pertimbangkan konvensi platform:
- Ikuti pola notifikasi khusus platform
- Patuhi pengaturan sistem
- Di Linux, tangani dependensi daemon:
- Periksa kesalahan yang dikembalikan oleh
SendNotification— daemon yang tidak tersedia menghasilkan kesalahan D-Bus - Dokumentasi paket atau README aplikasi sebaiknya menyatakan bahwa daemon notifikasi freedesktop diperlukan
Contoh
Pelajari contoh ini:
Referensi API
Pengelolaan Layanan
| Metode | Deskripsi |
|---|---|
New() |
Membuat layanan notifikasi baru |
Otorisasi Notifikasi
| Metode | Deskripsi |
|---|---|
RequestNotificationAuthorization() |
Meminta izin untuk menampilkan notifikasi (macOS) |
CheckNotificationAuthorization() |
Memeriksa status otorisasi notifikasi saat ini (macOS) |
Mengirim Notifikasi
| Metode | Deskripsi |
|---|---|
SendNotification(options NotificationOptions) |
Mengirim notifikasi dasar |
SendNotificationWithActions(options NotificationOptions) |
Mengirim notifikasi interaktif dengan tindakan |
UpdateNotification(options NotificationOptions) |
Memperbarui notifikasi yang sedang diproses berdasarkan ID (lihat Memperbarui Notifikasi) |
Kategori Notifikasi
| Metode | Deskripsi |
|---|---|
RegisterNotificationCategory(category NotificationCategory) |
Mendaftarkan kategori notifikasi yang dapat digunakan kembali |
RemoveNotificationCategory(categoryID string) |
Menghapus kategori yang sebelumnya didaftarkan |
Mengelola Notifikasi
| Metode | Deskripsi |
|---|---|
RemoveAllPendingNotifications() |
Menghapus semua notifikasi tertunda (hanya macOS dan Linux) |
RemovePendingNotification(identifier string) |
Menghapus notifikasi tertunda tertentu (hanya macOS dan Linux) |
RemoveAllDeliveredNotifications() |
Menghapus semua notifikasi yang telah dikirim (hanya macOS dan Linux) |
RemoveDeliveredNotification(identifier string) |
Menghapus notifikasi tertentu yang telah dikirim (hanya macOS dan Linux) |
RemoveNotification(identifier string) |
Menghapus notifikasi (khusus Linux) |
Penanganan Peristiwa
| Metode | Deskripsi |
|---|---|
OnNotificationResponse(callback func(result NotificationResult)) |
Mendaftarkan callback untuk respons notifikasi |
Struct dan Tipe
NotificationOptions
type NotificationOptions struct {
ID string // Unique identifier for the notification (required)
Title string // Main notification title (required)
Subtitle string // Subtitle text (macOS and Linux only)
Body string // Main notification content
CategoryID string // Category identifier for interactive notifications
Data map[string]interface{} // Custom data to associate with the notification
// Sound controls the sound played on delivery. nil = platform default.
Sound *NotificationSound
// Attachments are media files shown alongside the notification.
// macOS supports multiple attachments of any media type;
// Windows and Linux honour the first image-typed attachment.
Attachments []NotificationAttachment
// ThreadID groups related notifications together in
// Notification Center / Action Center / the Linux notification daemon.
ThreadID string
// InterruptionLevel controls priority. One of "passive",
// "active" (default), "timeSensitive", "critical".
InterruptionLevel string
// Schedule defers delivery. macOS uses a native trigger that survives
// restarts; Windows and Linux use an in-process timer that does NOT.
Schedule *NotificationSchedule
}NotificationSound
type NotificationSound struct {
Silent bool // If true, no sound is played
Name string // Named/bundled sound (see "Custom Sound" above)
}NotificationAttachment
type NotificationAttachment struct {
ID string // Optional identifier
Path string // Absolute filesystem path (macOS also accepts file:// URLs)
// Type is an optional placement/UTI hint:
// macOS: UTI like "public.png" / "public.audio" (often inferred)
// Windows: "hero" | "appLogoOverride" | "inline" (default "inline")
// Linux: ignored (always image-path hint)
Type string
}NotificationSchedule
// Exactly one of DelaySeconds or At must be set. At is Unix seconds (UTC).
type NotificationSchedule struct {
DelaySeconds int // Seconds from now until delivery
At int64 // Absolute Unix timestamp (seconds, UTC)
}Konstanta InterruptionLevel
const (
InterruptionLevelPassive = "passive"
InterruptionLevelActive = "active" // default
InterruptionLevelTimeSensitive = "timeSensitive"
InterruptionLevelCritical = "critical"
)NotificationCategory
type NotificationCategory struct {
ID string // Unique identifier for the category
Actions []NotificationAction // Button actions for the notification
HasReplyField bool // Whether to include a text input field
ReplyPlaceholder string // Placeholder text for the input field
ReplyButtonTitle string // Text for the reply button
}NotificationAction
type NotificationAction struct {
ID string // Unique identifier for the action
Title string // Button text
Destructive bool // Whether the action is destructive (macOS-specific)
}NotificationResponse
type NotificationResponse struct {
ID string // Notification identifier
ActionIdentifier string // Action that was triggered
CategoryID string // Category of the notification
Title string // Title of the notification
Subtitle string // Subtitle of the notification
Body string // Body text of the notification
UserText string // Text entered by the user
UserInfo map[string]interface{} // Custom data from the notification
}NotificationResult
type NotificationResult struct {
Response NotificationResponse // Response data
Error error // Any error that occurred
}