aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-12-12 16:39:55 +0100
committerFlorian Dold <florian.dold@gmail.com>2017-12-12 16:39:55 +0100
commitb5a4bcb247ec94ee99ca83c068d660574a36a0d7 (patch)
treeb6fe2b9aebc35f342f730a776ec9a50eb480caa6
parent1bcc5022c27fff2c28c38b3db12ac353cc7d3481 (diff)
show notification dot when balance changes (#5214)
-rw-r--r--src/wallet.ts24
-rw-r--r--src/webex/chromeBadge.ts37
-rw-r--r--src/webex/messages.ts4
-rw-r--r--src/webex/pages/popup.tsx3
-rw-r--r--src/webex/wxApi.ts4
-rw-r--r--src/webex/wxBackend.ts20
6 files changed, 91 insertions, 1 deletions
diff --git a/src/wallet.ts b/src/wallet.ts
index 5b658de85..9e8eb3f3e 100644
--- a/src/wallet.ts
+++ b/src/wallet.ts
@@ -247,6 +247,16 @@ export interface Badge {
* Stop indicating background activity.
*/
stopBusy(): void;
+
+ /**
+ * Show the notification in the badge.
+ */
+ showNotification(): void;
+
+ /**
+ * Stop showing the notification.
+ */
+ clearNotification(): void;
}
@@ -982,7 +992,7 @@ export class Wallet {
.put(Stores.purchases, t)
.putAll(Stores.coins, payCoinInfo.map((pci) => pci.updatedCoin))
.finish();
-
+ this.badge.showNotification();
this.notifier.notify();
}
@@ -1198,7 +1208,11 @@ export class Wallet {
return c;
}
await this.q().mutate(Stores.coins, coin.coinPub, mutateCoin)
+ // Show notifications only for accepted tips
+ this.badge.showNotification();
}
+ } else {
+ this.badge.showNotification();
}
this.notifier.notify();
@@ -1720,6 +1734,7 @@ export class Wallet {
console.log("suspending coin", c);
c.suspended = true;
q.put(Stores.coins, c);
+ this.badge.showNotification();
this.notifier.notify();
});
await q.finish();
@@ -2673,6 +2688,7 @@ export class Wallet {
.put(Stores.coinsReturns, coinsReturnRecord)
.putAll(Stores.coins, payCoinInfo.map((pci) => pci.updatedCoin))
.finish();
+ this.badge.showNotification();
this.notifier.notify();
this.depositReturnedCoins(coinsReturnRecord);
@@ -2835,6 +2851,7 @@ export class Wallet {
this.refresh(perm.coin_pub);
}
+ this.badge.showNotification();
this.notifier.notify();
}
@@ -2968,6 +2985,7 @@ export class Wallet {
}
await q.finish();
+ this.badge.showNotification();
this.notifier.notify();
}
@@ -3047,4 +3065,8 @@ export class Wallet {
// FIXME(#5210) also GC coins
}
+
+ clearNotification(): void {
+ this.badge.clearNotification();
+ }
}
diff --git a/src/webex/chromeBadge.ts b/src/webex/chromeBadge.ts
index 13add9b3f..3dfe94518 100644
--- a/src/webex/chromeBadge.ts
+++ b/src/webex/chromeBadge.ts
@@ -63,6 +63,11 @@ export class ChromeBadge implements Badge {
private gapWidth: number = 0;
/**
+ * Should we show the notification dot?
+ */
+ private hasNotification = false;
+
+ /**
* Maximum value for our rotationAngle, corresponds to 2 Pi.
*/
static rotationAngleMax = 1000;
@@ -150,6 +155,21 @@ export class ChromeBadge implements Badge {
// go back to the origin
this.ctx.translate(-this.canvas.width / 2, -this.canvas.height / 2);
+ if (this.hasNotification) {
+ // We draw a circle with a soft border in the
+ // lower right corner.
+ const r = 8;
+ const cw = this.canvas.width;
+ const ch = this.canvas.height;
+ this.ctx.beginPath();
+ this.ctx.arc(cw - r, ch - r, r, 0, 2 * Math.PI, false);
+ const gradient = this.ctx.createRadialGradient(cw - r, ch - r, r, cw - r, ch - r, 5);
+ gradient.addColorStop(0, "rgba(255, 255, 255, 1)");
+ gradient.addColorStop(1, "blue");
+ this.ctx.fillStyle = gradient;
+ this.ctx.fill();
+ }
+
// Allow running outside the extension for testing
// tslint:disable-next-line:no-string-literal
if (window["chrome"] && window.chrome["browserAction"]) {
@@ -211,6 +231,23 @@ export class ChromeBadge implements Badge {
rAF(step);
}
+ /**
+ * Draw the badge such that it shows the
+ * user that something happened (balance changed).
+ */
+ showNotification() {
+ this.hasNotification = true;
+ this.draw();
+ }
+
+ /**
+ * Draw the badge without the notification mark.
+ */
+ clearNotification() {
+ this.hasNotification = false;
+ this.draw();
+ }
+
startBusy() {
if (this.isBusy) {
return;
diff --git a/src/webex/messages.ts b/src/webex/messages.ts
index 7cc6c4259..44c9f166c 100644
--- a/src/webex/messages.ts
+++ b/src/webex/messages.ts
@@ -208,6 +208,10 @@ export interface MessageMap {
request: types.TipStatusRequest;
response: void;
};
+ "clear-notification": {
+ request: { };
+ response: void;
+ };
}
/**
diff --git a/src/webex/pages/popup.tsx b/src/webex/pages/popup.tsx
index 389be3b5c..6d1ff3b2b 100644
--- a/src/webex/pages/popup.tsx
+++ b/src/webex/pages/popup.tsx
@@ -566,4 +566,7 @@ const el = (
document.addEventListener("DOMContentLoaded", () => {
ReactDOM.render(el, document.getElementById("content")!);
+ // Will be used by the backend to detect when the popup gets closed,
+ // so we can clear notifications
+ chrome.runtime.connect({name: "popup"});
});
diff --git a/src/webex/wxApi.ts b/src/webex/wxApi.ts
index 61a45c024..2575eec90 100644
--- a/src/webex/wxApi.ts
+++ b/src/webex/wxApi.ts
@@ -381,3 +381,7 @@ export function acceptTip(merchantDomain: string, tipId: string): Promise<TipSta
export function processTipResponse(merchantDomain: string, tipId: string, tipResponse: TipResponse): Promise<void> {
return callBackend("process-tip-response", { merchantDomain, tipId, tipResponse });
}
+
+export function clearNotification(): Promise<void> {
+ return callBackend("clear-notification", { });
+}
diff --git a/src/webex/wxBackend.ts b/src/webex/wxBackend.ts
index a7757c68e..a804c73d1 100644
--- a/src/webex/wxBackend.ts
+++ b/src/webex/wxBackend.ts
@@ -337,6 +337,9 @@ function handleMessage(sender: MessageSender,
const req = GetTipPlanchetsRequest.checked(detail);
return needsWallet().getTipPlanchets(req.merchantDomain, req.tipId, req.amount, req.deadline, req.exchangeUrl, req.nextUrl);
}
+ case "clear-notification": {
+ return needsWallet().clearNotification();
+ }
default:
// Exhaustiveness check.
// See https://www.typescriptlang.org/docs/handbook/advanced-types.html
@@ -698,6 +701,23 @@ export async function wxMain() {
});
+
+ // Clear notifications both when the popop opens,
+ // as well when it closes.
+ chrome.runtime.onConnect.addListener((port) => {
+ if (port.name == "popup") {
+ if (currentWallet) {
+ currentWallet.clearNotification();
+ }
+ port.onDisconnect.addListener(() => {
+ if (currentWallet) {
+ currentWallet.clearNotification();
+ }
+ });
+ }
+ });
+
+
// Handlers for catching HTTP requests
chrome.webRequest.onHeadersReceived.addListener((details) => {
const wallet = currentWallet;