r1500 - in wit/js: . components services
Author: smaisonneuve Date: 2015-05-26 16:08:21 +0000 (Tue, 26 May 2015) New Revision: 1500 Url: http://forge.nuiton.org/projects/sandbox/repository/revisions/1500 Log: [Refactoring] Turning TimerService and UserActivityService into classed Modified: wit/js/components/Tags.js wit/js/main.js wit/js/services/SessionsService.js wit/js/services/TimerService.js wit/js/services/UserActivityService.js Modified: wit/js/components/Tags.js =================================================================== --- wit/js/components/Tags.js 2015-05-26 15:59:19 UTC (rev 1499) +++ wit/js/components/Tags.js 2015-05-26 16:08:21 UTC (rev 1500) @@ -3,6 +3,7 @@ var React = require("react"); var timer = require("../services/TimerService"); var InputTag = require("./InputTag"); +var InputTag = require("../components/InputTag.js"); class Tags extends React.Component { Modified: wit/js/main.js =================================================================== --- wit/js/main.js 2015-05-26 15:59:19 UTC (rev 1499) +++ wit/js/main.js 2015-05-26 16:08:21 UTC (rev 1500) @@ -7,7 +7,10 @@ // Alias // Total time during day -var noTimer = require("./services/NoTimerService"); +var timer = require("./services/TimerService.js"); +var user = require("./services/UserActivityService.js"); +var noTimer = require("./services/NoTimerService.js"); + noTimer.detect(); var GuiManager = require("./GuiManager"); Modified: wit/js/services/SessionsService.js =================================================================== --- wit/js/services/SessionsService.js 2015-05-26 15:59:19 UTC (rev 1499) +++ wit/js/services/SessionsService.js 2015-05-26 16:08:21 UTC (rev 1500) @@ -60,7 +60,7 @@ var rst; if (!startDate || !endDate) { - log.error("[UserActivityService] getSessions : parameter missing !"); + log.error("[SessionsService] getSessions : parameter missing !"); } else { var d1 = moment(startDate), d2 = moment(endDate); Modified: wit/js/services/TimerService.js =================================================================== --- wit/js/services/TimerService.js 2015-05-26 15:59:19 UTC (rev 1499) +++ wit/js/services/TimerService.js 2015-05-26 16:08:21 UTC (rev 1500) @@ -1,232 +1,246 @@ "use strict"; +var config = require("./ConfigurationService"); +var db = require("./database"); + var moment = require("moment"); -var db = require("./database.js"); var x11 = require("x11"); var log = require("loglevel"); var events = require("events"); var eventEmitter = new events.EventEmitter(); -var tags = ["wit", "js", "dev"]; -var time = null; -var idleTime = null; -var dayTime = 0; +class TimerService { + constructor() { -var historyIndex = -1; + this.tags = ["wit", "js", "dev"]; + this.time = null; + this.idleTime = null; + this.dayTime = 0; + this.timeChangeTimer = null; + this.historyIndex = -1; -x11.createClient(function(err0, display) { - if (err0) { - log.error(err0); - return; + this.initXClient(); } - var X = display.client; - X.require("screen-saver", function(err1, SS) { + initXClient() { + x11.createClient(function(err0, display) { + if (err0) { + log.error(err0); + return; + } - var queryIdle = function() { - SS.QueryInfo(display.screen[0].root, function(err2, info) { -// console.log('Idle time ' + info.idle + "ms"); + var X = display.client; + X.require("screen-saver", function(err1, SS) { - if (time) { - var configIdleTime = scope.config.getIdleTime(); - var durationIdleTime = moment.duration(configIdleTime, "m"); + var queryIdle = function() { + SS.QueryInfo(display.screen[0].root, function(err2, info) { + // console.log('Idle time ' + info.idle + "ms"); - if (info.idle >= durationIdleTime.asMilliseconds() && !idleTime) { - idleTime = new Date(); - eventEmitter.emit("onIdle"); - } - } + if (this.time) { + var configIdleTime = config.getIdleTime(); + var durationIdleTime = moment.duration(configIdleTime, "m"); - setTimeout(queryIdle, 1000); - }); - }; + if (info.idle >= durationIdleTime.asMilliseconds() && !this.idleTime) { + this.idleTime = new Date(); + eventEmitter.emit("onIdle"); + } + } - queryIdle(); - }); + setTimeout(queryIdle, 1000); + }.bind(this)); + }.bind(this); - X.on("error", log.error); -}); + queryIdle(); + }.bind(this)); -var timeChangeTimer = null; + X.on("error", log.error); + }.bind(this)); + } -var timeChange = function() { - clearTimeout(timeChangeTimer); + timeChange() { + clearTimeout(this.timeChangeTimer); - eventEmitter.emit("onTimeChanged"); - if (time) { - timeChangeTimer = setTimeout(timeChange.bind(), 1000); + eventEmitter.emit("onTimeChanged"); + if (this.time) { + this.timeChangeTimer = setTimeout(this.timeChange.bind(this), 1000); + } } -}; -var insertLog = function(t, start, end) { - dayTime += moment(end).diff(moment(start)); - db.insertLog(t, start, end); -}; + insertLog(t, start, end) { + this.dayTime += moment(end).diff(moment(start)); + db.insertLog(t, start, end); + }; -exports.start = function() { + start() { - // Come from to keep idle - if (time) { - var diff = moment(idleTime).diff(moment(time)); - time = moment().subtract(diff, "ms").toDate(); - } else { - time = new Date(); - } + // Come from to keep idle + if (this.time) { + var diff = moment(this.idleTime).diff(moment(this.time)); + this.time = moment().subtract(diff, "ms").toDate(); + } else { + this.time = new Date(); + } - idleTime = null; - historyIndex = -1; + this.idleTime = null; + this.historyIndex = -1; - timeChange(); + this.timeChange(); + } - scope.user.resumeActivityDetection(); -}; + stop(force) { -exports.stop = function(force) { + if (this.idleTime && force) { + this.time = null; + this.idleTime = null; + this.timeChange(); + } - if (idleTime && force) { - time = null; - idleTime = null; - timeChange(); + if (this.time && !this.idleTime) { + this.insertLog(this.tags, this.time, new Date()); + this.time = null; + this.timeChange(); + } } - if (time && !idleTime) { - insertLog(tags, time, new Date()); - time = null; - timeChange(); + getTime() { + if (this.time) { + var start = moment(); + var diff = moment(start.diff(this.time)).utcOffset(0); + return diff.format("HH:mm:ss"); + } } -}; -exports.getTime = function() { - if (time) { - var start = moment(); - var diff = moment(start.diff(time)).utcOffset(0); - return diff.format("HH:mm:ss"); + getTags() { + return this.tags; } -}; -exports.getTags = function() { - return tags; -}; + addTag(tag) { + this.tags.push(tag); + eventEmitter.emit("onTagsChanged"); + } -exports.addTag = function(tag) { - tags.push(tag); - eventEmitter.emit("onTagsChanged"); -}; + removeTag(index) { + this.tags.splice(index, 1); + eventEmitter.emit("onTagsChanged"); + } -exports.removeTag = function(index) { - tags.splice(index, 1); - eventEmitter.emit("onTagsChanged"); -}; + subscribeTagsChanged(callback) { + eventEmitter.on("onTagsChanged", callback); + } + subscribeTimeChanged(callback) { + eventEmitter.on("onTimeChanged", callback); + } -exports.subscribeTagsChanged = function(callback) { - eventEmitter.on("onTagsChanged", callback); -}; + subscribeIdle(callback) { + eventEmitter.on("onIdle", callback); + } -exports.subscribeTimeChanged = function(callback) { - eventEmitter.on("onTimeChanged", callback); -}; + unsubscribeTagsChanged(callback) { + eventEmitter.removeListener("onTagsChanged", callback); + } -exports.subscribeIdle = function(callback) { - eventEmitter.on("onIdle", callback); -}; + unsubscribeTimeChanged(callback) { + eventEmitter.removeListener("onTimeChanged", callback); + } -exports.unsubscribeTagsChanged = function(callback) { - eventEmitter.removeListener("onTagsChanged", callback); -}; + unsubscribeIdle(callback) { + eventEmitter.removeListener("onIdle", callback); + } -exports.unsubscribeTimeChanged = function(callback) { - eventEmitter.removeListener("onTimeChanged", callback); -}; + keepIdle() { + this.idleTime = null; + } -exports.unsubscribeIdle = function(callback) { - eventEmitter.removeListener("onIdle", callback); -}; + removeIdle() { + this.insertLog(this.tags, this.time, this.idleTime); + this.time = null; + this.idleTime = null; -exports.keepIdle = function() { - scope.user.resumeActivityDetection(); - idleTime = null; -}; + this.timeChange(); -exports.removeIdle = function() { - insertLog(tags, time, idleTime); - time = null; - idleTime = null; + this.start(); + } - timeChange(); + editTime(value) { + if (this.time) { + var d = moment.duration(value); + this.idleTime = moment().subtract(d.asMilliseconds(), "ms").toDate(); + this.reassignIdle(); + } + } - exports.start(); -}; - -exports.editTime = function(value) { - if (time) { - var d = moment.duration(value); - idleTime = moment().subtract(d.asMilliseconds(), "ms").toDate(); - this.reassignIdle(); + reassignIdle() { + this.reassignTimeFrom(this.idleTime); } -}; -exports.reassignIdle = function() { - exports.reassignTimeFrom(idleTime); -}; + reassignTimeFrom(newStartTime) { + this.insertLog(this.tags, this.time, newStartTime); + this.time = newStartTime; + this.idleTime = new Date(); -exports.reassignTimeFrom = function(newStartTime) { - insertLog(tags, time, newStartTime); - time = newStartTime; - idleTime = new Date(); + clearTimeout(this.timeChangeTimer); + eventEmitter.emit("onTimeChanged"); + }; - clearTimeout(timeChangeTimer); - eventEmitter.emit("onTimeChanged"); -}; + getDayTime() { + var diff = this.dayTime; + if (this.time) { + var now = moment(); + diff += now.diff(this.time); + } -exports.getDayTime = function() { - var diff = dayTime; - if (time) { - var now = moment(); - diff += now.diff(time); + var value = moment(diff).utcOffset(0); + return value.format("HH:mm:ss"); } - var value = moment(diff).utcOffset(0); - return value.format("HH:mm:ss"); -}; + deleteLog(id) { + db.deleteLog(id); + } -exports.deleteLog = function(id) { - db.deleteLog(id); -}; + setTagsFromHistory() { -// History -var setTagsFromHistory = function() { + db.getHistory(this.historyIndex) + .then(function(logs) { - db.getHistory(historyIndex) - .then(function(logs) { + if (logs && logs.length) { + var row = logs[0]; + this.tags = row.tags.slice(0); + } else { + this.tags = []; + } + eventEmitter.emit("onTagsChanged"); + }.bind(this)); + } - if (logs && logs.length) { - var row = logs[0]; - tags = row.tags.slice(0); - } else { - tags = []; + prevHistory() { + this.historyIndex++; + this.setTagsFromHistory(); + } + + nextHistory() { + if (this.historyIndex === -1) { + return; } - eventEmitter.emit("onTagsChanged"); - }); -}; -exports.prevHistory = function() { - historyIndex++; + this.historyIndex--; + this.setTagsFromHistory(); + } - setTagsFromHistory(); -}; - -exports.nextHistory = function() { - if (historyIndex === -1) { - return; + getLastTags() { + return db.getLastTags(); } +} - historyIndex--; +// Export TimerService as a singleton - setTagsFromHistory(); +TimerService.instance = null; +TimerService.getInstance = function() { + if (this.instance === null) { + this.instance = new TimerService(); + } + return this.instance; }; -exports.getLastTags = function() { - return db.getLastTags(); -}; +module.exports = TimerService.getInstance(); Modified: wit/js/services/UserActivityService.js =================================================================== --- wit/js/services/UserActivityService.js 2015-05-26 15:59:19 UTC (rev 1499) +++ wit/js/services/UserActivityService.js 2015-05-26 16:08:21 UTC (rev 1500) @@ -1,5 +1,9 @@ "use strict"; +var config = require("./ConfigurationService"); +var sessions = require("./SessionsService"); +var timer = require("./TimerService"); + var x11 = require("x11"); var xprop = require("xprop"); var moment = require("moment"); @@ -8,216 +12,224 @@ var events = require("events"); var eventEmitter = new events.EventEmitter(); -var activityChangeTimer; -var disableActivityDetection = false; +class UserActivityService { + constructor() { + this.activityChangeTimer = null; + this.disableActivityDetection = false; + this.initActivityListener(); + this.subscribeToTimerChange(); + } -/////////////// -// Utilities // -/////////////// + /** + * Listen to active window change and window title change + * Some part of the code has been derived from : + * http://stackoverflow.com/questions/19840459/linux-get-notification-on-focuse... + */ + initActivityListener() { + x11.createClient(function(err, display) { + var xClient = display.client; -var onActiveWindowChange = function(xClient, ev) { - if (ev.name === "PropertyNotify") { + xClient.ChangeWindowAttributes(display.screen[0].root, { + eventMask: x11.eventMask.PropertyChange + }); - xClient.GetAtomName(ev.atom, function(err, name) { + // Init windows session with the currently active window + //addWindowSession(X, display.screen[0].root); - // if the property change refers to the currently active window, retrieve new active window name + // Listen to client display events to identify when the currently active window has change + xClient.on("event", this.onActiveWindowChange.bind(this, xClient)); + }.bind(this)); + } - if (name === "_NET_ACTIVE_WINDOW") { - - registerWindowEvents(xClient, ev); - addWindowSession(xClient, ev); - - } else if (name === "_NET_WM_NAME") { - - updateWindowSession(ev); + /** + * Subscriber to timer change : + * If timer change occured while activity change detection is on going, + * stop activity change detection process (means the user has handled it) + */ + subscribeToTimerChange() { + timer.subscribeTimeChanged(function() { + if (!timer.getTime()) { + clearTimeout(this.activityChangeTimer); } - }); + }.bind(this)); } -}; -var getActiveWindowId = function(xClient, ev) { - return new Promise(function(resolve, reject) { + onActiveWindowChange(xClient, ev) { + if (ev.name === "PropertyNotify") { - if (!ev.wid) { + xClient.GetAtomName(ev.atom, function(err, name) { - reject(); + // if the property change refers to the currently active window, retrieve new active window name - } else { + if (name === "_NET_ACTIVE_WINDOW") { - xClient.GetProperty(0, ev.wid, ev.atom, xClient.atoms.WINDOW, 0, 4, function(err, prop) { - if (err || !prop.data.length) { - log.warn("Couldn't retrieve active window property"); - reject(); + this.registerWindowEvents(xClient, ev); + this.addWindowSession(xClient, ev); - } else { - var wid = prop.data.readUInt32LE(0); + } else if (name === "_NET_WM_NAME") { - if (wid) { - resolve(wid); - - } else { - log.warn("Couldn't retrieve active window property"); - reject(); - } + this.updateWindowSession(ev); } - }); + }.bind(this)); } + } - }); -}; + getActiveWindowId(xClient, ev) { + return new Promise(function(resolve, reject) { -var getWindowName = function(windowId) { - return new Promise(function(resolve, reject) { + if (!ev.wid) { - if (!windowId) { + reject(); - reject(); + } else { - } else { + xClient.GetProperty(0, ev.wid, ev.atom, xClient.atoms.WINDOW, 0, 4, function(err, prop) { + if (err || !prop.data.length) { + log.warn("Couldn't retrieve active window property"); + reject(); - xprop({prop: "_NET_WM_NAME", id: windowId}, function(err, properties) { + } else { + var wid = prop.data.readUInt32LE(0); - if (err) { - log.warn("Couldn't retrieve window name for id :", windowId); - reject(); + if (wid) { + resolve(wid); - } else { - resolve(properties.length && properties[0].value); - } - }); - } - }); -}; + } else { + log.warn("Couldn't retrieve active window property"); + reject(); + } + } + }); + } -var registerWindowEvents = function(xClient, ev) { - getActiveWindowId(xClient, ev) - .then(function(wid) { - xClient.ChangeWindowAttributes(wid, { - eventMask: x11.eventMask.PropertyChange }); - }); -}; + } -var setupActivityDetection = function(session) { - if (disableActivityDetection || !session || !scope.timer.getTime()) { + getWindowName(windowId) { + return new Promise(function(resolve, reject) { - clearTimeout(activityChangeTimer); // stop activity detection + if (!windowId) { - } else { + reject(); - var now = moment(); - if (now.diff(session.startDate, "m") >= scope.config.getActivityTime()) { + } else { - // The user has stayed more than "config.getActivityTime()" minutes on a window - // and now has just switched to another window. - // If it stays at list as long as he did on the previous one, let's notify it to him + xprop({prop: "_NET_WM_NAME", id: windowId}, function(err, properties) { - activityChangeTimer = setTimeout( - eventEmitter.emit.bind(eventEmitter, "onActivityChange", now.toDate()), - moment.duration(scope.config.getActivityTime(), "m").as("ms") - ); - activityChangeTimer.crtActivityName = session.name; - activityChangeTimer.changeDetectedDate = now.toDate(); + if (err) { + log.warn("Couldn't retrieve window name for id :", windowId); + reject(); - } else if (session.name === activityChangeTimer.crtActivityName) { + } else { + resolve(properties.length && properties[0].value); + } + }); + } + }); + } - // The user is back to the window from which we initiated the activity timer, - // it seems to indicate that he is still working on the same activity. Let's clear the timer. - - clearTimeout(activityChangeTimer); - } + registerWindowEvents(xClient, ev) { + this.getActiveWindowId(xClient, ev) + .then(function(wid) { + xClient.ChangeWindowAttributes(wid, { + eventMask: x11.eventMask.PropertyChange + }); + }); } -}; -/** - * Current active window is still the same - * but it's title has changed. - * Trace it by creating a new session with the same shape attributes than the previous one - */ -var updateWindowSession = function(ev) { - return getWindowName(ev.wid) - .then(function(windowName) { + setupActivityDetection(session) { + if (this.disableActivityDetection || !session || !timer.getTime()) { - // Let's create a new session but with same color attributes than the last one, - // since the active window has not really changed, only some of its attributes + clearTimeout(this.activityChangeTimer); // stop activity detection - var crtSession = scope.sessions.getCrtSession(); - if (crtSession && crtSession.name !== windowName) { - scope.sessions.createNewSession(windowName, crtSession.color); - } + } else { - }); -}; + var now = moment(); + if (now.diff(session.startDate, "m") >= config.getActivityTime()) { -/** - * Create a new window session - */ -var addWindowSession = function(xClient, ev) { - var ss = scope.sessions; - var crtSession = ss.getCrtSession(); + // The user has stayed more than "config.getActivityTime()" minutes on a window + // and now has just switched to another window. + // If it stays at list as long as he did on the previous one, let's notify it to him - return getActiveWindowId(xClient, ev) - .then(getWindowName) - .then(ss.createNewSession.bind(ss)) - .then(setupActivityDetection.bind(null, crtSession)); -}; + this.activityChangeTimer = setTimeout( + eventEmitter.emit.bind(eventEmitter, "onActivityChange", now.toDate()), + moment.duration(config.getActivityTime(), "m").as("ms") + ); + this.activityChangeTimer.crtActivityName = session.name; + this.activityChangeTimer.changeDetectedDate = now.toDate(); -/////////////// -// Exports // -/////////////// + } else if (session.name === this.activityChangeTimer.crtActivityName) { -/** - * Offers an api for services interesting in activity change detection - */ -exports.subscribeActivityChange = function(callback) { - eventEmitter.on("onActivityChange", callback); -}; + // The user is back to the window from which we initiated the activity timer, + // it seems to indicate that he is still working on the same activity. Let's clear the timer. -exports.getActivityChangeDetectedDate = function() { - return activityChangeTimer && activityChangeTimer.changeDetectedDate; -}; + clearTimeout(this.activityChangeTimer); + } + } + } -exports.suspendActivityDetection = function() { - disableActivityDetection = true; - clearTimeout(activityChangeTimer); -}; + /** + * Current active window is still the same + * but it's title has changed. + * Trace it by creating a new session with the same shape attributes than the previous one + */ + updateWindowSession(ev) { + return this.getWindowName(ev.wid) + .then(function(windowName) { -exports.resumeActivityDetection = function() { - disableActivityDetection = false; -}; + // Let's create a new session but with same color attributes than the last one, + // since the active window has not really changed, only some of its attributes + var crtSession = sessions.getCrtSession(); + if (crtSession && crtSession.name !== windowName) { + sessions.createNewSession(windowName, crtSession.color); + } -/////////////////////////////// -// Init activity detection // -/////////////////////////////// + }); + } -/* - * Listen to active window change and window title change - * Some part of the code has been derived from : - * http://stackoverflow.com/questions/19840459/linux-get-notification-on-focuse... - */ -x11.createClient(function(err, display) { - var xClient = display.client; + /** + * Create a new window session + */ + addWindowSession(xClient, ev) { + var crtSession = sessions.getCrtSession(); - xClient.ChangeWindowAttributes(display.screen[0].root, { - eventMask: x11.eventMask.PropertyChange - }); + return this.getActiveWindowId(xClient, ev) + .then(this.getWindowName.bind(this)) + .then(sessions.createNewSession.bind(sessions)) + .then(this.setupActivityDetection.bind(this, crtSession)); + }; - // Init windows session with the currently active window -// addWindowSession(X, display.screen[0].root); + /** + * Offers an api for services interesting in activity change detection + */ + subscribeActivityChange(callback) { + eventEmitter.on("onActivityChange", callback); + } - // Listen to client display events to identify when the currently active window has change - xClient.on("event", onActiveWindowChange.bind(null, xClient)); -}); + getActivityChangeDetectedDate() { + return this.activityChangeTimer && this.activityChangeTimer.changeDetectedDate; + } -/** - * Subscriber to timer change : - * If timer change occured while activity change detection is on going, - * stop activity change detection process (means the user has handled it) - */ -scope.timer.subscribeTimeChanged(function() { - if (!scope.timer.getTime()) { - clearTimeout(activityChangeTimer); + suspendActivityDetection() { + this.disableActivityDetection = true; + clearTimeout(this.activityChangeTimer); } -}); + + resumeActivityDetection() { + this.disableActivityDetection = false; + } +} + +// Export UserActivityService as a singleton + +UserActivityService.instance = null; +UserActivityService.getInstance = function() { + if (this.instance === null) { + this.instance = new UserActivityService(); + } + return this.instance; +}; + +module.exports = UserActivityService.getInstance();
participants (1)
-
smaisonneuveďź users.nuiton.org