-
Notifications
You must be signed in to change notification settings - Fork 2
/
notify.go
167 lines (147 loc) · 3.27 KB
/
notify.go
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
package ui
import (
"sync"
"time"
"github.com/aditya-K2/utils"
"github.com/aditya-K2/tview"
"github.com/gdamore/tcell/v2"
)
var (
maxNotifications = 3
pm sync.Mutex
notAvailable = -1
posArr = positionArray{}
c chan *notification
)
// Start Notification Service
func InitNotifier() {
for _m := maxNotifications; _m != 0; _m-- {
posArr = append(posArr, true)
}
c = make(chan *notification, maxNotifications)
routine()
}
// notification Primitive
type notification struct {
*tview.Box
Text string
Position int
close chan time.Time
timer time.Duration
}
// Array for all available positions where the notification can be displayed.
type positionArray []bool
// Check If there is a position available.
func (p *positionArray) Available() bool {
var t = false
pm.Lock()
for _, v := range *p {
t = t || v
}
pm.Unlock()
return t
}
func (p *positionArray) GetNextPosition() int {
pm.Lock()
v := *p
for k := range v {
if v[k] {
v[k] = false
pm.Unlock()
return k
}
}
pm.Unlock()
return notAvailable
}
// Free a position
func (p *positionArray) Free(i int) {
pm.Lock()
v := *p
v[i] = true
pm.Unlock()
}
// Get A Pointer to A Notification Struct
func newNotificationWithTimer(s string, t time.Duration) *notification {
return ¬ification{
Box: tview.NewBox(),
Text: s,
timer: t,
close: nil,
}
}
// Get A Pointer to A Notification Struct with a close channel
func newNotificationWithChan(s string, c chan time.Time) *notification {
return ¬ification{
Box: tview.NewBox(),
Text: s,
close: c,
}
}
// Draw Function for the Notification Primitive
func (self *notification) Draw(screen tcell.Screen) {
termDetails := utils.GetWidth()
pos := (self.Position*3 + self.Position + 1)
var (
COL int = int(termDetails.Col)
TEXTLENGTH int = len(self.Text)
HEIGHT int = 3
TextPosition int = 1
)
self.Box.SetBackgroundColor(tcell.ColorBlack)
self.SetRect(COL-(TEXTLENGTH+7), pos, TEXTLENGTH+4, HEIGHT)
self.DrawForSubclass(screen, self.Box)
tview.Print(screen, self.Text,
COL-(TEXTLENGTH+5), pos+TextPosition, TEXTLENGTH,
tview.AlignCenter, tcell.ColorWhite)
}
// this routine checks for available position and sends notification if
// position is available.
func routine() {
go func() {
for {
val := <-c
// Wait until a new position isn't available
for !posArr.Available() {
continue
}
notify(val)
}
}()
}
func notify(n *notification) {
go func() {
currentTime := time.Now().String()
npos := posArr.GetNextPosition()
// Ensure a position is available.
if npos == notAvailable {
for !posArr.Available() {
}
npos = posArr.GetNextPosition()
}
n.Position = npos
Ui.Pages.AddPage(currentTime, n, false, true)
Ui.App.SetFocus(Ui.MainS)
if n.close != nil {
<-n.close
} else {
time.Sleep(n.timer)
}
Ui.Pages.RemovePage(currentTime)
posArr.Free(npos)
Ui.App.SetFocus(Ui.MainS)
}()
}
func SendNotification(text string) {
SendNotificationWithTimer(text, time.Second)
}
func SendNotificationWithTimer(text string, t time.Duration) {
go func() {
c <- newNotificationWithTimer(text, t)
}()
}
func SendNotificationWithChan(text string, close chan time.Time) {
go func() {
c <- newNotificationWithChan(text, close)
}()
}