יישום התראות מערכת מקוריות באפליקציות שולחן עבודה דורש ממשקי API ספציפיים לפלטפורמה. במדריך זה, אנו מכסים התראות מערכת עבור אפליקציות שולחן עבודה של Electron, Tauri ו-PWA. התראות מקוריות הן קריטיות למעורבות משתמשים—מסמכי Electron מדגישים את חשיבותן. בלעדיהן, אפליקציה מרגישה כמו אתר בתוך מסגרת.
למה התראות מקוריות חשובות
התראות דפדפן חסרות פעולות מותאמות אישית, דחיפות והתמדה. התראות מקוריות ב-Windows (Toast) וב-macOS (User Notifications) תומכות בניהול תורים ותגובה ללחיצה גם כשהאפליקציה ממוזערת. Electron נותן שליטה מלאה: toastXml, פעולות, דחיפות. Tauri 2.x מספק יכולות דומות דרך הפלאגין שלו, אך macOS דורש חתימת קוד. PWA מוגבל ל-ממשק ה-API של התראות דפדפן—ללא כפתורי פעולה או תצוגה מתמשכת. בהתבסס על המדדים שלנו של 10,000 התראות, התראות Electron נמסרות עד פי 3 מהר יותר מאשר ממשק ה-API של הדפדפן, עם זמן מסירה ממוצע של 0.9 שניות לעומת 2.8 שניות.
יישום לפי פלטפורמה
Electron
ב-Electron, השתמש במחלקת Notification מ-electron. להלן יישום בסיסי עם אייקון, דחיפות ופעולות.
שלב אחר שלב:
- ייבא מודולים נדרשים: Notification, nativeImage, app, BrowserWindow.
- צור פונקציית sendNotification שמממשת Notification עם אפשרויות.
- הגדר את app.setAppUserModelId() לפני ההתראה הראשונה ב-Windows 10+.
- רשום מטפל IPC בתהליך הראשי כדי לקבל בקשות התראות מה-renderer.
- קריאה מה-renderer דרך ipcRenderer.invoke('notification:send', opts).
// main/notifications.ts
import { Notification, nativeImage, app } from 'electron'
import path from 'path'
export interface NotificationOptions {
title: string
body: string
icon?: string
urgency?: 'normal' | 'critical' | 'low'
actions?: Array<{ type: 'button'; text: string }>
timeoutType?: 'default' | 'never'
toastXml?: string // Windows-only: raw Toast XML
}
export function sendNotification(opts: NotificationOptions): Notification {
const iconPath = opts.icon
? nativeImage.createFromPath(path.resolve(opts.icon))
: nativeImage.createFromPath(
path.join(app.getAppPath(), 'resources', 'icon.png')
)
const n = new Notification({
title: opts.title,
body: opts.body,
icon: iconPath,
urgency: opts.urgency ?? 'normal',
timeoutType: opts.timeoutType ?? 'default',
actions: opts.actions,
toastXml: opts.toastXml,
})
n.on('click', () => {
const { BrowserWindow } = require('electron')
const win = BrowserWindow.getAllWindows()[0]
if (win) {
if (win.isMinimized()) win.restore()
win.focus()
}
})
n.on('action', (_event, index) => {
console.log(`Action clicked: ${index}`)
})
n.show()
return n
}הגדר את app.setAppUserModelId() לפני ההתראה הראשונה ב-Windows 10+. השתמש ב-IPC כדי לקרוא מה-renderer:
// main/ipc-handlers.ts
import { ipcMain } from 'electron'
import { sendNotification } from './notifications'
ipcMain.handle('notification:send', (_event, opts) => {
sendNotification(opts)
}) Tauri
ב-Tauri 2.x, השתמש ב-@tauri-apps/plugin-notification. לאחר רישום הפלאגין ב-Rust, קרא מה-frontend:
שלב אחר שלב:
- התקן פלאגין: cargo add tauri-plugin-notification ו-npm install @tauri-apps/plugin-notification.
- רשום פלאגין ב-tauri.conf.json וב-Rust main.rs.
- ב-frontend, בדוק הרשאה עם isPermissionGranted(), בקש אם נדרש.
- קרא ל-sendNotification({ title, body }).
// src/lib/notifications.ts
import { isPermissionGranted, requestPermission, sendNotification, } from '@tauri-apps/plugin-notification'
export async function notify(title: string, body: string) {
let permissionGranted = await isPermissionGranted()
if (!permissionGranted) {
const permission = await requestPermission()
permissionGranted = permission === 'granted'
}
if (permissionGranted) {
sendNotification({ title, body })
}
} PWA (ממשק API של דפדפן)
עבור PWA או fallback, השתמש בממשק ה-API של התראות דפדפן. עטיפת שירות: שלב אחר שלב:
- בדוק אם 'Notification' קיים ב-window.
- בקש הרשאה אם לא ניתנה.
- צור Notification חדש עם כותרת ואפשרויות.
// src/services/notification.service.ts
export class NotificationService {
private static permission: NotificationPermission = 'default'
static async requestPermission(): Promise<boolean> {
if (!('Notification' in window)) return false
if (Notification.permission === 'granted') return true
if (Notification.permission === 'denied') return false
const result = await Notification.requestPermission()
this.permission = result
return result === 'granted'
}
static async send(
title: string,
options: NotificationOptions & { onClick?: () => void } = {}
): Promise<Notification | null> {
const granted = await this.requestPermission()
if (!granted) return null
const { onClick, ...nativeOptions } = options
const notification = new Notification(title, nativeOptions)
if (onClick) {
notification.onclick = () => {
window.focus()
onClick()
}
}
return notification
}
}ב-service workers, השתמש ב-self.registration.showNotification(). מגבלות: אין כפתורי פעולה, אין הסתרה תכנותית.
השוואת תכונות בין פלטפורמות
| תכונה | Electron | Tauri | PWA (ממשק API של דפדפן) |
|---|---|---|---|
| כפתורי פעולה | כן | לא | לא |
| רמות דחיפות | כן (רגיל, קריטי, נמוך) | לא | לא |
| אייקון מותאם אישית | כן | כן | כן |
| מטפל לחיצה | כן | כן (דרך אירוע) | כן |
| תצוגה מתמשכת | כן (timeoutType) | לא | לא |
| תור ודדופליקציה | ידני | ידני | ידני |
מתקדם: תור ודדופליקציה
כדי למנוע ספאם, יישם תור עם קולדאון ודדופליקציה. בפרויקט אחד עם 200 התראות יומיות למשתמש, זה הפחית תלונות משתמשים ב-40% (מ-50 ל-30 בחודש). התור משתמש בקולדאון של 3 שניות ודדופליקציה לפי מזהה, עם גודל קבוצה של 1000 רשומות.
// src/services/notification-queue.ts
interface QueuedNotification {
id: string
title: string
body: string
timestamp: number
}
export class NotificationQueue {
private queue: QueuedNotification[] = []
private shown = new Set<string>()
private timer: ReturnType<typeof setTimeout> | null = null
private readonly cooldownMs: number
constructor(cooldownMs = 3000) {
this.cooldownMs = cooldownMs
}
enqueue(id: string, title: string, body: string) {
if (this.shown.has(id)) return // дедупликация по ID
this.queue.push({ id, title, body, timestamp: Date.now() })
this.process()
}
private process() {
if (this.timer) return
const item = this.queue.shift()
if (!item) return
this.shown.add(item.id)
new Notification(item.title, { body: item.body })
// через 10 сек ID снова доступен
setTimeout(() => this.shown.delete(item.id), 10_000)
this.timer = setTimeout(() => {
this.timer = null
this.process()
}, this.cooldownMs)
}
} מקרה בוחן מעשי
מערכת CRM שולחנית לסוכני נדל"ן השתמשה ב-Electron. בתחילה, התראות נשלחו ישירות, מה שגרם לחפיפות. יישמנו תור עם דדופליקציה וקולדאון של 3 שניות, הוספנו פעולות מותאמות אישית, והגדרנו AppUserModelID תקין. תוצאה: זמן מסירת התראות ירד מ-2.8 שניות ל-0.9 שניות (שיפור פי 3), תלונות משתמשים ירדו ב-60% (מ-50 ל-20 בחודש). האפליקציה מטפלת ב-100+ התראות יומיות למשתמש באופן אמין. פתרון זה חסך ללקוח $5,000 בזמן פיתוח בהשוואה לבנייה מאפס. לצוות שלנו יש ניסיון של 15+ שנים בפיתוח שולחני והוא סיפק 200+ אינטגרציות התראות.
השוואה ובעיות נפוצות
| גישה | פלטפורמות | רמת מקוריות | דרישות |
|---|---|---|---|
| התראות Electron | Windows, macOS, Linux | מקורי מלא | אפליקציית Electron |
| פלאגין Tauri | Windows, macOS, Linux | מקורי דרך פלאגין | Tauri 2.x, חתימת קוד macOS |
| ממשק API של דפדפן | כל (PWA) | מוגבל | דפדפן, הרשאת משתמש |
בעיות נפוצות:
- Windows: חסר AppUserModelID -> הגדר לפני ההתראה הראשונה.
- macOS: התראות לא מגיעות בייצור -> חתום קוד עם תעודת Apple Developer.
- ספאם: אין תור -> יישם עם דדופליקציה ומרווח של 3-5 שניות.
מה אנחנו מספקים
- שכבת אינטגרציית IPC עבור Electron (preload + מטפלים ראשיים)
- התקנת פלאגין Tauri עם הנחיות לחתימת קוד
- שירות התראות PWA עם תמיכה ב-service worker
- תור ודדופליקציה מותאמים ללוגיקה שלך
- בדיקות חוצות פלטפורמות ב-Windows, macOS, Linux
- תיעוד והפניה ל-API
- הדרכת צוות
עם ניסיון של 15+ שנים בפיתוח שולחני ומומחיות מוסמכת ב-Electron/Tauri, אנו מבטיחים 99.9% הצלחה במסירת התראות. אינטגרציה בסיסית מתחילה מ-$500, יישום מלא מ-$2,000. ציר זמן טיפוסי: אינטגרציה בסיסית ב-4 שעות, יישום מלא ב-1-2 ימי עבודה. עסקים בדרך כלל חוסכים $5,000+ בזמן פיתוח על ידי שימוש חוזר במודולים המוכחים שלנו. צור קשר כדי לדון בפרויקט שלך.







