diff --git a/client/core/core.go b/client/core/core.go index 18530b168e..512ce90963 100644 --- a/client/core/core.go +++ b/client/core/core.go @@ -3125,13 +3125,11 @@ func (c *Core) handleConnectEvent(host string, connected bool) { } c.connMtx.Unlock() statusStr := "connected" - lvl := db.Success if !connected { statusStr = "disconnected" - lvl = db.WarningLevel } details := fmt.Sprintf("DEX at %s has %s", host, statusStr) - c.notify(newConnEventNote(fmt.Sprintf("DEX %s", statusStr), host, connected, details, lvl)) + c.notify(newConnEventNote(fmt.Sprintf("DEX %s", statusStr), host, connected, details, db.Poke)) c.refreshUser() } diff --git a/client/webserver/live_test.go b/client/webserver/live_test.go index ac201a9574..35694c0a59 100644 --- a/client/webserver/live_test.go +++ b/client/webserver/live_test.go @@ -46,6 +46,7 @@ var ( forceDisconnectWallet bool wipeWalletBalance bool gapWidthFactor = 1.0 // Should be 0 < gapWidthFactor <= 1.0 + randomPokes = false ) func dummySettings() map[string]string { @@ -925,6 +926,31 @@ out: } } +func (c *TCore) runRandomPokes() { + nextWait := func() time.Duration { + return time.Duration(float64(time.Second)*rand.Float64()) * 5 + } + chars := []byte("abcd efgh ijkl mnop qrst uvwx yz123") + numChars := len(chars) + randStr := func(maxLen int) string { + strLen := rand.Intn(maxLen) + b := make([]byte, 0, strLen) + for i := 0; i < strLen; i++ { + b = append(b, chars[rand.Intn(numChars)]) + } + return string(b) + } + for { + select { + case <-time.NewTimer(nextWait()).C: + note := db.NewNotification(randStr(20), randStr(20), randStr(100), db.Poke) + c.noteFeed <- ¬e + case <-tCtx.Done(): + return + } + } +} + func TestServer(t *testing.T) { // Register dummy drivers for unimplemented assets. asset.Register(22, &TDriver{}) // mona @@ -939,6 +965,7 @@ func TestServer(t *testing.T) { register := true forceDisconnectWallet = true gapWidthFactor = 0.2 + randomPokes = true var shutdown context.CancelFunc tCtx, shutdown = context.WithCancel(context.Background()) @@ -968,5 +995,8 @@ func TestServer(t *testing.T) { t.Fatalf("Connect error: %v", err) } go tCore.runEpochs() + if randomPokes { + go tCore.runRandomPokes() + } cm.Wait() } diff --git a/client/webserver/site/src/css/main.scss b/client/webserver/site/src/css/main.scss index 292ab52b07..f888ac4a85 100644 --- a/client/webserver/site/src/css/main.scss +++ b/client/webserver/site/src/css/main.scss @@ -249,30 +249,29 @@ div.note-indicator.warn { div.poke-note { position: fixed; right: 20px; - top: 100%; - height: 30px; - transition: top 1s; - background-color: black; - color: $font-color-dark; - border-radius: 5px 5px 0 0; + bottom: 0; + display: flex; + flex-direction: column; + align-items: flex-end; + border-radius: 4px; z-index: 1000; - border-width: 1px; - border-style: solid; - border-color: #444; max-width: 90%; & > span { display: inline-block; + background-color: black; + color: $font-color-dark; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + font-size: 15px; + border-bottom: 1px solid #7777; + padding: 4px 10px; + line-height: 1; + margin: 3px 0 0; } } -div.poke-note.active { - top: calc(100% - 30px); -} - #noteBox, #profileBox { position: absolute; diff --git a/client/webserver/site/src/css/main_dark.scss b/client/webserver/site/src/css/main_dark.scss index 51629c568b..f737041b1a 100644 --- a/client/webserver/site/src/css/main_dark.scss +++ b/client/webserver/site/src/css/main_dark.scss @@ -90,10 +90,9 @@ body.dark { border-color: white; } - div.poke-note { + div.poke-note > span { background-color: white; color: $font-color-light; - border-color: #aaa; } .buycolor { diff --git a/client/webserver/site/src/html/bodybuilder.tmpl b/client/webserver/site/src/html/bodybuilder.tmpl index afab7fa680..578f2e61aa 100644 --- a/client/webserver/site/src/html/bodybuilder.tmpl +++ b/client/webserver/site/src/html/bodybuilder.tmpl @@ -11,7 +11,9 @@ -
Here is a poke note.
+
+ +
{{template "header" .}} {{end}} diff --git a/client/webserver/site/src/js/app.js b/client/webserver/site/src/js/app.js index 79fe6f55cb..5aa92d5693 100644 --- a/client/webserver/site/src/js/app.js +++ b/client/webserver/site/src/js/app.js @@ -223,7 +223,9 @@ export default class Application { */ attachHeader () { this.header = idel(document.body, 'header') - this.pokeNote = idel(document.body, 'pokeNote') + this.pokeNotes = idel(document.body, 'pokeNote') + this.pokeTmpl = Doc.tmplElement(this.pokeNotes, 'note') + this.pokeTmpl.remove() this.tooltip = idel(document.body, 'tooltip') const pg = this.page = Doc.parsePage(this.header, [ 'noteIndicator', 'noteBox', 'noteList', 'noteTemplate', @@ -428,15 +430,15 @@ export default class Application { if (note.severity < ntfn.POKE) return // Poke notifications have their own display. if (note.severity === ntfn.POKE) { - this.pokeNote.firstChild.textContent = `${note.subject}: ${note.details}` - this.pokeNote.classList.add('active') - if (this.pokeNote.timer) { - clearTimeout(this.pokeNote.timer) - } - this.pokeNote.timer = setTimeout(() => { - this.pokeNote.classList.remove('active') - delete this.pokeNote.timer - }, 5000) + const span = this.pokeTmpl.cloneNode(true) + span.textContent = `${note.subject}: ${note.details}` + this.pokeNotes.appendChild(span) + setTimeout(async () => { + await Doc.animate(500, progress => { + span.style.opacity = 1 - progress + }) + span.remove() + }, 6000) return } // Success and higher severity go to the bell dropdown.