Skip to content

Commit 5384531

Browse files
committed
Merge branch 'feature-track-interval' of https://github.com/Stigmatoz/web-activity-time-tracker
2 parents 1b74a67 + 9259411 commit 5384531

File tree

12 files changed

+390
-52
lines changed

12 files changed

+390
-52
lines changed

src/icons/heat-map-16.png

477 Bytes
Loading

src/icons/pie-chart.png

617 Bytes
Loading

src/index.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,14 @@
2424
<a id="btnByDays">By days</a>
2525
<a id="settings">Settings</a>
2626
</div>
27+
<div id="blockForChartBtn">
28+
<a class="button active chart-btn chart-btn-donut" id="donutChartBtn">Common chart</a>
29+
<a class="button chart-btn chart-btn-heatmap" id="heatMapChartBtn">Time chart</a>
30+
</div>
2731
<div id="chart"></div>
32+
<div id="timeChart"></div>
2833
<div id="resultTable" class="list-of-site"></div>
29-
<div id="total" class="inline-flex"></div>
34+
<div id="total"></div>
3035
<div id="byDays" class="calendar-block"></div>
3136

3237
<svg class="height-0">

src/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
"name": "Web Activity Time Tracker",
55
"short_name": "Web Time Tracker",
6-
"version": "1.1.3",
6+
"version": "1.2.0",
77
"minimum_chrome_version": "26",
88

99
"description": "Track and limit time your activity in the browser.",

src/scripts/activity.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class Activity {
1010
if (currentTab !== tab.url) {
1111
isDifferentUrl = true;
1212
}
13-
this.setCurrentActiveTab(domain);
13+
1414
if (this.isNewUrl(domain) && !this.isInBlackList(domain)) {
1515
var favicon = tab.favIconUrl;
1616
if (favicon === undefined) {
@@ -20,7 +20,8 @@ class Activity {
2020
tabs.push(newTab);
2121
}
2222

23-
if (isDifferentUrl) {
23+
if (isDifferentUrl && !this.isInBlackList(domain)) {
24+
this.setCurrentActiveTab(domain);
2425
var tabUrl = this.getTab(domain);
2526
if (tabUrl !== undefined)
2627
tabUrl.incCounter();
@@ -99,10 +100,21 @@ class Activity {
99100
}
100101

101102
setCurrentActiveTab(domain) {
103+
this.closeIntervalForCurrentTab();
102104
currentTab = domain;
103105
}
104106

105107
clearCurrentActiveTab() {
108+
this.closeIntervalForCurrentTab();
106109
currentTab = '';
107110
}
111+
112+
closeIntervalForCurrentTab() {
113+
if (currentTab !== '') {
114+
var tabUrl = this.getTab(currentTab);
115+
if (tabUrl !== undefined)
116+
tabUrl.closeInterval();
117+
currentTab = '';
118+
}
119+
}
108120
};

src/scripts/background.js

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,29 @@ function backgroundCheck() {
3030
activity.addTab(activeTab);
3131
}
3232

33-
if (tab !== undefined) {
34-
activity.setCurrentActiveTab(tab.url);
35-
chrome.idle.queryState(parseInt(setting_interval_inactivity), function (state) {
36-
if (state === 'active') {
37-
mainTRacker(activeUrl, tab, activeTab);
38-
}
39-
else checkDOM(state, activeUrl, tab, activeTab);
33+
if (activity.isInBlackList(activeUrl)) {
34+
chrome.browserAction.setBadgeBackgroundColor({ color: '#FF0000' })
35+
chrome.browserAction.setBadgeText({
36+
tabId: activeTab.id,
37+
text: 'n/a'
4038
});
4139
} else {
42-
if (activity.isInBlackList(activeUrl)) {
43-
chrome.browserAction.setBadgeBackgroundColor({ color: '#FF0000' })
44-
chrome.browserAction.setBadgeText({
45-
tabId: activeTab.id,
46-
text: 'n/a'
40+
if (tab !== undefined) {
41+
if (currentTab !== tab.url) {
42+
tab.incCounter();
43+
activity.setCurrentActiveTab(tab.url);
44+
}
45+
chrome.idle.queryState(parseInt(setting_interval_inactivity), function (state) {
46+
if (state === 'active') {
47+
mainTRacker(activeUrl, tab, activeTab);
48+
}
49+
else checkDOM(state, activeUrl, tab, activeTab);
4750
});
4851
}
4952
}
5053
}
54+
} else {
55+
activity.closeIntervalForCurrentTab();
5156
}
5257
});
5358
}
@@ -60,21 +65,13 @@ function mainTRacker(activeUrl, tab, activeTab) {
6065
tab.incSummaryTime();
6166
}
6267
if (setting_view_in_badge === true) {
63-
if (activity.isInBlackList(activeUrl)) {
64-
chrome.browserAction.setBadgeBackgroundColor({ color: '#FF0000' })
65-
chrome.browserAction.setBadgeText({
66-
tabId: activeTab.id,
67-
text: 'n/a'
68-
});
69-
} else {
70-
chrome.browserAction.setBadgeBackgroundColor({ color: [0, 0, 0, 0] })
71-
var today = new Date().toLocaleDateString("en-US");
72-
var summary = tab.days.find(s => s.date === today).summary;
73-
chrome.browserAction.setBadgeText({
74-
tabId: activeTab.id,
75-
text: String(convertSummaryTimeToBadgeString(summary))
76-
});
77-
}
68+
chrome.browserAction.setBadgeBackgroundColor({ color: [0, 0, 0, 0] })
69+
var today = new Date().toLocaleDateString("en-US");
70+
var summary = tab.days.find(s => s.date === today).summary;
71+
chrome.browserAction.setBadgeText({
72+
tabId: activeTab.id,
73+
text: String(convertSummaryTimeToBadgeString(summary))
74+
});
7875
} else {
7976
chrome.browserAction.setBadgeBackgroundColor({ color: [0, 0, 0, 0] })
8077
chrome.browserAction.setBadgeText({
@@ -100,9 +97,10 @@ function isVideoPlayedOnPage() {
10097
}
10198

10299
function checkDOM(state, activeUrl, tab, activeTab) {
103-
if (state === 'idle') {
100+
if (state === 'idle' && isDomainEquals(activeUrl, "youtube.com")) {
104101
checkPermissions(mainTRacker, activeUrl, tab, activeTab);
105102
}
103+
else activity.closeIntervalForCurrentTab();
106104
}
107105

108106
function checkPermissions(callback, activeUrl, tab, activeTab) {
@@ -114,6 +112,7 @@ function checkPermissions(callback, activeUrl, tab, activeTab) {
114112
chrome.tabs.executeScript({ code: "var videoElement = document.getElementsByTagName('video')[0]; (videoElement !== undefined && videoElement.currentTime > 0 && !videoElement.paused && !videoElement.ended && videoElement.readyState > 2);" }, (results) => {
115113
if (results !== undefined && results[0] !== undefined && results[0] === true)
116114
callback(activeUrl, tab, activeTab);
115+
else activity.closeIntervalForCurrentTab();
117116
});
118117
}
119118
});
@@ -159,22 +158,22 @@ function addListener() {
159158
checkSettingsImEmpty();
160159
}
161160
});
162-
chrome.storage.onChanged.addListener(function(changes, namespace) {
161+
chrome.storage.onChanged.addListener(function (changes, namespace) {
163162
for (var key in changes) {
164-
if (key === STORAGE_BLACK_LIST){
163+
if (key === STORAGE_BLACK_LIST) {
165164
loadBlackList();
166165
}
167-
if (key === STORAGE_RESTRICTION_LIST){
166+
if (key === STORAGE_RESTRICTION_LIST) {
168167
loadRestrictionList();
169168
}
170-
if (key === SETTINGS_INTERVAL_INACTIVITY){
169+
if (key === SETTINGS_INTERVAL_INACTIVITY) {
171170
storage.getSettings(SETTINGS_INTERVAL_INACTIVITY, function (item) { setting_interval_inactivity = item; });
172171
}
173-
if (key === SETTINGS_VIEW_TIME_IN_BADGE){
172+
if (key === SETTINGS_VIEW_TIME_IN_BADGE) {
174173
storage.getSettings(SETTINGS_VIEW_TIME_IN_BADGE, function (item) { setting_view_in_badge = item; });
175174
}
176175
}
177-
});
176+
});
178177

179178
chrome.runtime.setUninstallURL("https://docs.google.com/forms/d/e/1FAIpQLSdImHtvey6sg5mzsQwWfAQscgZOOV52blSf9HkywSXJhuQQHg/viewform");
180179
}
@@ -200,7 +199,7 @@ function loadRestrictionList() {
200199
})
201200
}
202201

203-
function loadSettings(){
202+
function loadSettings() {
204203
storage.getSettings(SETTINGS_INTERVAL_INACTIVITY, function (item) { setting_interval_inactivity = item; });
205204
storage.getSettings(SETTINGS_VIEW_TIME_IN_BADGE, function (item) { setting_view_in_badge = item; });
206205
}

src/scripts/chart/chart-core.js

Lines changed: 178 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,8 @@ function donutChart() {
226226
}
227227

228228
function barChart(data) {
229-
var margin = { top: 5, right: 5, bottom: 25, left: 5 },
230-
width = 485,
229+
var margin = { top: 25, right: 5, bottom: 25, left: 5 },
230+
width = 555,
231231
height = 160;
232232

233233
// set the ranges
@@ -282,4 +282,180 @@ function barChart(data) {
282282

283283
if (data.length > 9)
284284
document.querySelectorAll('#barChart g.tick ').forEach(element => { element.remove() });
285+
}
286+
287+
function drawIntervalChart(data) {
288+
data.forEach(function (item) {
289+
var hFrom = getHourFrom(item.interval);
290+
var hTo = getHourTo(item.interval);
291+
if (hFrom != hTo) {
292+
var sourceTimeFrom = item.interval.split('-')[0].split(':');
293+
var sourceTimeTo = item.interval.split('-')[1].split(':');
294+
var timeTo = sourceTimeFrom[0] + ":" + 59 + ":" + 59;
295+
var timeFrom = sourceTimeTo[0] + ":" + 00 + ":" + 00;
296+
data.push({ "domain": item.domain, "interval": item.interval.split('-')[0] + "-" + timeTo });
297+
data.push({ "domain": item.domain, "interval": timeFrom + "-" + item.interval.split('-')[1] });
298+
}
299+
});
300+
301+
var margin = { top: 5, right: 10, bottom: 20, left: 20 },
302+
width = 580 - margin.left - margin.right,
303+
height = 410 - margin.top - margin.bottom;
304+
305+
//linear 24 hour scale
306+
var y = d3.scaleLinear()
307+
.domain([0, 60])
308+
.range([height, 0]);
309+
310+
//vertical axis
311+
var yAxis = d3.axisLeft()
312+
.ticks(10)
313+
.scale(y);
314+
315+
var x = d3.scaleLinear()
316+
.domain([0, 24])
317+
.range([0, width]);
318+
319+
//vertical axis
320+
var xAxis = d3.axisBottom()
321+
.ticks(24)
322+
.scale(x)
323+
324+
var tickDistance = 4.38;
325+
326+
var tooltip = d3.select("#timeChart")
327+
.append("div")
328+
.style("opacity", 0)
329+
.style("display", "none")
330+
.style("position", "absolute")
331+
.attr("class", "tooltip")
332+
.style("background-color", "white")
333+
.style("border", "solid")
334+
.style("border-width", "1px")
335+
.style("border-radius", "5px")
336+
.style("padding", "5px")
337+
338+
// Three function that change the tooltip when user hover / move / leave a cell
339+
var mouseover = function (d) {
340+
tooltip
341+
.style("opacity", 1)
342+
.style("display", "block")
343+
d3.select(this)
344+
.style("stroke", "black")
345+
.style("stroke-width", "0.5px")
346+
.style("opacity", 1)
347+
}
348+
var mousemove = function (d) {
349+
tooltip
350+
.html(d.domain + "<br>" + d.interval)
351+
.style("left", (d3.mouse(this)[0]) + 10 + "px")
352+
.style("top", (d3.mouse(this)[1]) + 30 + "px")
353+
}
354+
var mouseleave = function (d) {
355+
tooltip
356+
.style("opacity", 0)
357+
.style("display", "none")
358+
d3.select(this)
359+
.style("stroke", "none")
360+
.style("opacity", 0.8)
361+
}
362+
363+
//create the svg
364+
var svg = d3.select("#timeChart").append("svg")
365+
.attr("width", width + margin.left + margin.right)
366+
.attr("height", height + margin.top + margin.bottom)
367+
.append("g")
368+
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
369+
370+
//draw the axis.
371+
svg.append("g")
372+
.attr("class", "x axis")
373+
.attr("transform", "translate(0," + height + ")")
374+
.attr("class", "label")
375+
.call(xAxis)
376+
.append("text")
377+
.text("Value");
378+
379+
// Add a y-axis with label.
380+
svg.append("g")
381+
.attr("class", "y axis")
382+
.call(yAxis)
383+
.append("text")
384+
.attr("class", "label")
385+
.attr("y", 6)
386+
.attr("dy", ".71em")
387+
.attr("text-anchor", "end")
388+
.attr("transform", "rotate(-90)")
389+
.text("Value");
390+
391+
svg.append("g")
392+
.attr("class", "grid")
393+
.attr("transform", "translate(0," + height + ")")
394+
.call(make_x_axis()
395+
.tickSize(-height, 0, 0)
396+
)
397+
398+
svg.append("g")
399+
.attr("class", "grid")
400+
.call(make_y_axis()
401+
.tickSize(-width, 0, 0)
402+
)
403+
404+
//draw the bars, offset y and bar height based on data
405+
svg.selectAll(".bar")
406+
.data(data)
407+
.enter()
408+
.append("rect")
409+
.style("fill", "orangered")
410+
.style("stroke", "#f1f1f1")
411+
.style("stroke-width", "1")
412+
.attr("class", "bar")
413+
.attr("x", function (d) {
414+
return x(getHourFrom(d.interval)) + 2;
415+
})
416+
.attr("width", 20)
417+
.attr("y", function (d) {
418+
return y(getMinutesTo(d.interval)) - 1;
419+
})
420+
.attr("height", function (d) {
421+
var offset = getMinutesTo(d.interval) - getMinutesFrom(d.interval);
422+
if (offset == 0)
423+
return 1;
424+
else return offset * tickDistance;
425+
})
426+
.on("mouseover", mouseover)
427+
.on("mousemove", mousemove)
428+
.on("mouseleave", mouseleave);
429+
430+
function make_x_axis() {
431+
return d3.axisBottom()
432+
.scale(x)
433+
.ticks(24)
434+
}
435+
436+
function make_y_axis() {
437+
return d3.axisLeft()
438+
.scale(y)
439+
.ticks(10)
440+
}
441+
442+
function getHourFrom(interval) {
443+
var time = interval.split('-')[0];
444+
return time.split(':')[0];
445+
}
446+
447+
function getHourTo(interval) {
448+
var time = interval.split('-')[1];
449+
return time.split(':')[0];
450+
}
451+
452+
function getMinutesFrom(interval) {
453+
var time = interval.split('-')[0];
454+
return time.split(':')[1];
455+
}
456+
457+
function getMinutesTo(interval) {
458+
var time = interval.split('-')[1];
459+
return time.split(':')[1];
460+
}
285461
}

0 commit comments

Comments
 (0)