Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: background.js

Issue 11161031: Show notifications on startup (Chrome) (Closed)
Patch Set: Addressed issues (except for the animation) Created July 22, 2013, 12:27 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « .hgsubstate ('k') | icons/notification-critical.png » ('j') | notification.js » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: background.js
===================================================================
--- a/background.js
+++ b/background.js
@@ -33,6 +33,7 @@
var Prefs = require("prefs").Prefs;
var Synchronizer = require("synchronizer").Synchronizer;
var Utils = require("utils").Utils;
+var Notification = require("notification").Notification;
// Some types cannot be distinguished
RegExpFilter.typeMap.OBJECT_SUBREQUEST = RegExpFilter.typeMap.OBJECT;
@@ -107,6 +108,8 @@
return (result instanceof WhitelistFilter ? result : null);
}
+var activeNotification = null;
+
// Adds or removes page action icon according to options.
function refreshIconAndContextMenu(tab)
{
@@ -116,7 +119,11 @@
var excluded = isWhitelisted(tab.url);
var iconFilename = excluded ? "icons/abp-19-whitelisted.png" : "icons/abp-19.png";
- chrome.pageAction.setIcon({tabId: tab.id, path: iconFilename});
+
+ if (activeNotification)
+ setNotificationPageAction(tab, iconFilename);
Wladimir Palant 2013/07/22 14:18:36 setNotificationPageAction() won't do anything for
Felix Dahlke 2013/07/22 15:10:22 Yes, it was like that. In patch set 4, all notific
+ else
+ chrome.pageAction.setIcon({tabId: tab.id, path: iconFilename});
// Only show icon for pages we can influence (http: and https:)
if(/^https?:/.test(tab.url))
@@ -135,6 +142,64 @@
}
}
+function loadImages(imageFiles, callback)
+{
+ var images = {};
+ var imagesLoaded = 0;
+ imageFiles.forEach(function(imageFile)
+ {
+ var image = new Image();
+ image.src = imageFile;
+ image.addEventListener("load", function()
+ {
+ images[imageFile] = image;
+ if (++imagesLoaded === imageFiles.length)
+ callback(images);
+ });
+ });
+}
+
+var iconAnimationTimer = null;
+
+function stopIconAnimation()
+{
+ if (!iconAnimationTimer)
+ return;
+
+ clearTimeout(iconAnimationTimer);
+ iconAnimationTimer = null;
+ chrome.tabs.getAllInWindow(null, function(tabs)
+ {
+ tabs.forEach(refreshIconAndContextMenu);
+ activeNotification = null;
Wladimir Palant 2013/07/22 14:18:36 Shouldn't activeNotification be reset before calli
Felix Dahlke 2013/07/22 15:10:22 Yes, I fixed that in patch set 4.
+ });
+}
+
+function setNotificationPageAction(tab, iconFileName)
+{
+ if (activeNotification.severity !== "critical")
+ return;
+
+ stopIconAnimation();
+
+ var notificationIconFile = "icons/notification-critical.png";
+ var iconFiles = [iconFileName, notificationIconFile];
+ loadImages(iconFiles, function(images)
+ {
+ var abpIcon = images[iconFileName];
+ var notificationIcon = images[notificationIconFile];
+ var canvas = document.createElement("canvas");
+ canvas.width = abpIcon.width;
+ canvas.height = abpIcon.height;
+ var context = canvas.getContext("2d");
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ context.drawImage(abpIcon, 0, 0);
+ context.drawImage(notificationIcon, 0, 0);
+ var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
Wladimir Palant 2013/07/22 14:18:36 The code to combine two images with some opacity a
Felix Dahlke 2013/07/22 15:10:22 Not necessary anymore, as of patch set 4.
+ chrome.pageAction.setIcon({tabId: tab.id, imageData: imageData});
+ });
+}
+
/**
* Old versions stored filter data in the localStorage object, this will import
* it into FilterStorage properly.
@@ -473,6 +538,89 @@
}
}
+function startInformationNotificationAnimation()
+{
+ stopIconAnimation();
+
+ var abpIconFile = "icons/abp-19.png";
Wladimir Palant 2013/07/22 14:18:36 This still hardcodes the icon and fails to conside
Felix Dahlke 2013/07/22 15:10:22 Has been fixed in patch set 4. But yeah, second co
Wladimir Palant 2013/07/23 07:25:04 No, we can still work with a single global timer -
Felix Dahlke 2013/07/23 10:38:08 Done. I do prefer this, just wasn't able to come u
+ var notificationIconFile = "icons/notification-information.png";
+ var iconFiles = [abpIconFile, notificationIconFile];
+ loadImages(iconFiles, function(images)
+ {
+ var abpIcon = images[abpIconFile];
+ var notificationIcon = images[notificationIconFile];
+ var canvas = document.createElement("canvas");
+ canvas.width = abpIcon.width;
+ canvas.height = abpIcon.height;
+ var context = canvas.getContext("2d");
+
+ var animationStartTime = Date.now();
+ var animationInterval = 1000 / 10;
+ function animationStep()
+ {
+ var timeElapsed = Date.now() - animationStartTime;
+ var duration = 3000;
+ var animationTime = timeElapsed % duration;
+ var delay = 1000;
+ var fadeInEndTime = duration / 2 - delay / 2;
+ var fadeOutStartTime = fadeInEndTime + delay;
+
+ var opacity;
+ if (animationTime < fadeInEndTime)
+ opacity = animationTime / fadeInEndTime;
+ else if (animationTime > fadeOutStartTime)
+ opacity = 1 - (animationTime - fadeOutStartTime)
+ / (duration - fadeOutStartTime);
Wladimir Palant 2013/07/22 14:18:36 Pretty complicated and IMHO not really necessary c
Felix Dahlke 2013/07/22 15:10:22 It's not really possible to get smooth animations
Felix Dahlke 2013/07/22 15:16:45 But I definitely prefer how you approached the del
Wladimir Palant 2013/07/23 07:25:04 You don't have a smooth animation right now, exact
Felix Dahlke 2013/07/23 10:38:08 Implemented this as you prefer it, since it's not
+
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ context.globalAlpha = 1;
+ context.drawImage(abpIcon, 0, 0);
+ context.globalAlpha = opacity;
+ context.drawImage(notificationIcon, 0, 0);
+ var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
+
+ chrome.tabs.getSelected(null, function(tab)
+ {
+ chrome.pageAction.setIcon({tabId: tab.id, imageData: imageData});
+ iconAnimationTimer = setTimeout(animationStep, animationInterval);
+ });
+ }
+ animationStep();
+ });
+}
+
+function showInformationNotification()
+{
+ activeNotification.onClicked = function()
+ {
+ stopIconAnimation();
+ activeNotification = null;
+ };
+
+ startInformationNotificationAnimation();
+}
+
+function showCriticalNotification()
+{
+ var notification = webkitNotifications.createHTMLNotification("notification.html");
+ notification.show();
+}
+
+function showNotification(notification)
+{
+ activeNotification = notification;
+
+ if (notification.severity === "critical")
+ showCriticalNotification();
+ else
+ showInformationNotification();
+
+ chrome.tabs.getAllInWindow(null, function(tabs)
+ {
+ tabs.forEach(refreshIconAndContextMenu);
+ });
+}
+
/**
* This function is a hack - we only know the tabId and document URL for a
* message but we need to know the frame ID. Try to find it in webRequest's
@@ -609,3 +757,10 @@
if(changeInfo.status == "loading")
refreshIconAndContextMenu(tab);
});
+
+setTimeout(function()
+{
+ var notificationToShow = Notification.getNextToShow();
+ if (notificationToShow)
+ showNotification(notificationToShow);
+}, 3 * 60 * 1000);
« no previous file with comments | « .hgsubstate ('k') | icons/notification-critical.png » ('j') | notification.js » ('J')

Powered by Google App Engine
This is Rietveld