File: notification.go

package info (click to toggle)
go-dlib 5.6.0.9%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 2,740 kB
  • sloc: ansic: 4,664; xml: 1,456; makefile: 20; sh: 15
file content (183 lines) | stat: -rw-r--r-- 4,651 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
 * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd.
 *
 * Author:     jouyouyun <jouyouwen717@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package notify

import (
	"errors"
	"runtime"
	"sync"

	"github.com/godbus/dbus"
	"pkg.deepin.io/lib/event"
)

type ActionCallback func(n *Notification, action string)
type _HintMap map[string]dbus.Variant

type Notification struct {
	id           uint32
	AppName      string
	Summary      string
	Body         string
	Icon         string
	Timeout      int32
	closedReason ClosedReason
	mu           sync.Mutex

	actions   []string
	actionMap map[string]ActionCallback
	hints     _HintMap
	// event closed (n *Notification, reason ClosedReason)
	closed *event.Event

	actionInvokedConnectRet      func()
	notificationClosedConnectRet func()
}

// Create a new Notification.
// summary text is required, but all other paramters are optional.
func NewNotification(summary, body, icon string) *Notification {
	n := &Notification{
		Summary:      summary,
		Body:         body,
		Icon:         icon,
		Timeout:      ExpiresDefault,
		hints:        make(_HintMap),
		closedReason: ClosedReasonInvalid,
		actionMap:    make(map[string]ActionCallback),
		closed:       event.New(func(_n *Notification, reason ClosedReason) {}),
	}

	runtime.SetFinalizer(n, func(_n *Notification) { _n.Destroy() })
	return n
}

func (n *Notification) Closed() *event.Event {
	return n.closed
}

func (n *Notification) Destroy() {
	if n.actionInvokedConnectRet != nil {
		n.actionInvokedConnectRet()
		n.actionInvokedConnectRet = nil
	}

	if n.notificationClosedConnectRet != nil {
		n.notificationClosedConnectRet()
		n.notificationClosedConnectRet = nil
	}

	runtime.SetFinalizer(n, nil)
}

// Updates the notification text and icon.
// This won't send the update out and display it on the screen.
// For that, you will need to call Show()
func (n *Notification) Update(summary, body, icon string) {
	n.Summary = summary
	n.Body = body
	n.Icon = icon
}

func (n *Notification) getAppName() string {
	if n.AppName == "" {
		return defaultAppName
	}
	return n.AppName
}

// Tells the notification server to display the notification on the screen.
func (n *Notification) Show() error {
	n.mu.Lock()
	defer n.mu.Unlock()
	if n.actionInvokedConnectRet == nil {
		n.actionInvokedConnectRet = notifier.ConnectActionInvoked(func(id uint32, action string) {
			if n.id != id {
				return
			}

			callback := n.actionMap[action]
			if callback != nil {
				callback(n, action)
			}
		})
	}

	if n.notificationClosedConnectRet == nil {
		n.notificationClosedConnectRet = notifier.ConnectNotificationClosed(func(id, reason uint32) {
			if n.id != id {
				return
			}
			n.closedReason = ClosedReason(reason)
			_ = n.closed.Trigger(n, ClosedReason(reason))
		})
	}

	id, err := notifier.Notify(n.getAppName(), n.id, n.Icon, n.Summary, n.Body, n.actions, n.hints, n.Timeout)
	if err != nil {
		return err
	}
	n.id = id
	return nil
}

func (n *Notification) SetHint(key string, value interface{}) {
	n.hints[key] = dbus.MakeVariant(value)
}

func (n *Notification) ClearHints() {
	n.hints = make(_HintMap)
}

func (n *Notification) AddAction(action, label string, callback ActionCallback) {
	if action == "" || label == "" || callback == nil {
		return
	}

	n.actions = append(n.actions, action, label)
	n.actionMap[action] = callback
}

func (n *Notification) ClearActions() {
	n.actions = nil
	n.actionMap = make(map[string]ActionCallback)
}

// Sets the category of this notification.
// This can be used by the notification server to filter or display the data in a certain way.
func (n *Notification) SetCategory(category string) {
	n.SetHint(HintCategory, category)
}

// Sets the urgency level of this notification.
func (n *Notification) SetUrgency(urgency byte) {
	n.SetHint(HintUrgency, urgency)
}

func (n *Notification) Close() error {
	if n.id == 0 {
		return errors.New("notification id is 0")
	}
	return notifier.CloseNotification(n.id)
}

func (n *Notification) GetClosedReason() ClosedReason {
	return n.closedReason
}