aboutsummaryrefslogtreecommitdiff
path: root/lib/wallet/chromeBadge.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/wallet/chromeBadge.ts')
-rw-r--r--lib/wallet/chromeBadge.ts118
1 files changed, 118 insertions, 0 deletions
diff --git a/lib/wallet/chromeBadge.ts b/lib/wallet/chromeBadge.ts
new file mode 100644
index 000000000..2443378b2
--- /dev/null
+++ b/lib/wallet/chromeBadge.ts
@@ -0,0 +1,118 @@
+/*
+ This file is part of TALER
+ (C) 2016 INRIA
+
+ TALER 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, or (at your option) any later version.
+
+ TALER 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import {
+ Badge
+} from "./wallet";
+
+
+/**
+ * Polyfill for requestAnimationFrame, which
+ * doesn't work from a background page.
+ */
+function rAF(cb: (ts: number) => void) {
+ window.setTimeout(() => {
+ cb(performance.now());
+ }, 100);
+}
+
+
+export class ChromeBadge implements Badge {
+ canvas: HTMLCanvasElement;
+ ctx: CanvasRenderingContext2D;
+ talerLogo: HTMLImageElement;
+ isBusy: boolean = false;
+ rotationAngle: number = 0;
+ static rotationAngleMax = 50000;
+
+ constructor() {
+ let bg = chrome.extension.getBackgroundPage();
+ this.canvas = bg.document.createElement("canvas");
+ this.canvas.width = 32;
+ this.canvas.height = 32;
+ this.ctx = this.canvas.getContext("2d")!;
+
+ this.talerLogo = bg.document.getElementById("taler-logo") as HTMLImageElement;
+ if (!(this.talerLogo instanceof HTMLImageElement)) {
+ throw Error();
+ }
+
+ this.draw();
+ }
+
+ /**
+ * Draw the badge based on the current state.
+ */
+ private draw() {
+ // Reset to identity
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ this.ctx.setTransform(1, 0, 0, 1, 0, 0);
+ this.ctx.translate(this.canvas.width / 2, this.canvas.height / 2);
+ this.ctx.rotate(this.rotationAngle / ChromeBadge.rotationAngleMax * Math.PI * 2);
+ this.ctx.translate(-this.canvas.width / 2, -this.canvas.height / 2);
+ this.ctx.drawImage(this.talerLogo,
+ 0,
+ 0,
+ this.talerLogo.width,
+ this.talerLogo.height,
+ 0, 0, this.canvas.width, this.canvas.height);
+
+ let imageData = this.ctx.getImageData(0,
+ 0,
+ this.canvas.width,
+ this.canvas.height);
+ chrome.browserAction.setIcon({imageData});
+ }
+
+ private animate() {
+ let bg: Window = chrome.extension.getBackgroundPage();
+ let start: number|undefined = undefined;
+ let step = (timestamp: number) => {
+ if (!start) {
+ start = timestamp;
+ }
+ let delta = (timestamp - start);
+ if (!this.isBusy && this.rotationAngle + delta >= ChromeBadge.rotationAngleMax) {
+ // stop if we're close enough to origin
+ this.rotationAngle = 0;
+ } else {
+ this.rotationAngle = (this.rotationAngle + timestamp - start) % ChromeBadge.rotationAngleMax;
+ }
+ if (this.isBusy || this.rotationAngle != 0) {
+ rAF(step);
+ }
+ this.draw();
+ };
+ rAF(step);
+ }
+
+ setText(s: string) {
+ chrome.browserAction.setBadgeText({text: s});
+ }
+
+ setColor(c: string) {
+ chrome.browserAction.setBadgeBackgroundColor({color: c});
+ }
+
+ startBusy() {
+ this.isBusy = true;
+ this.animate();
+ }
+
+ stopBusy() {
+ this.isBusy = false;
+ }
+} \ No newline at end of file