17
.gitattributes
vendored
Normal file
17
.gitattributes
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
.bowerrc text eol=lf
|
||||
.jshintignore text eol=lf
|
||||
AUTHORS text eol=lf
|
||||
LICENSE text eol=lf
|
||||
.csslintrc text eol=lf
|
||||
*.less text eol=lf
|
||||
*.html text eol=lf
|
||||
*.js text eol=lf
|
||||
*.json text eol=lf
|
||||
*.css text eol=lf
|
||||
*.jsx text eol=lf
|
||||
.gitignore text eol=lf
|
||||
.gitattributes text eol=lf
|
||||
.gitmodules text eol=lf
|
||||
.jshintrc text eol=lf
|
||||
*.md text eol=lf
|
||||
*.rst text eol=lf
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -26,9 +26,11 @@ node_modules
|
||||
|
||||
.DS_Store
|
||||
|
||||
vendor/
|
||||
vendor/bower_components
|
||||
|
||||
.idea
|
||||
|
||||
# Generated chrome extension
|
||||
public/
|
||||
web-ext-artifacts/
|
||||
.web-extension-id
|
||||
|
||||
0
.gitmodules
vendored
Normal file
0
.gitmodules
vendored
Normal file
@@ -1,16 +1,16 @@
|
||||
/* global chrome */
|
||||
/* global browser */
|
||||
|
||||
var React = require('react');
|
||||
|
||||
var MainList = React.createClass({
|
||||
|
||||
_openOptionsPage: function() {
|
||||
if (chrome.runtime.openOptionsPage) {
|
||||
if (browser.runtime.openOptionsPage) {
|
||||
// New way to open options pages, if supported (Chrome 42+).
|
||||
chrome.runtime.openOptionsPage();
|
||||
browser.runtime.openOptionsPage();
|
||||
} else {
|
||||
// Reasonable fallback.
|
||||
window.open(chrome.runtime.getURL('options.html'));
|
||||
window.open(browser.runtime.getURL('options.html'));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global chrome */
|
||||
/* global browser */
|
||||
|
||||
var React = require('react');
|
||||
var ReactCSSTransitionGroup = require('react-addons-css-transition-group');
|
||||
@@ -37,13 +37,13 @@ var Options = React.createClass({
|
||||
restoreSettings: function () {
|
||||
var that = this;
|
||||
|
||||
chrome.storage.sync.get({
|
||||
browser.storage.sync.get({
|
||||
theme: config.theme,
|
||||
blacklist: '',
|
||||
whitelist: '',
|
||||
loggingType: config.loggingType,
|
||||
loggingStyle: config.loggingStyle
|
||||
}, function (items) {
|
||||
}).then(function (items) {
|
||||
that.setState({
|
||||
theme: items.theme,
|
||||
blacklist: items.blacklist,
|
||||
@@ -75,13 +75,13 @@ var Options = React.createClass({
|
||||
var whitelist = that.state.whitelist.trim();
|
||||
|
||||
// Sync options with google storage.
|
||||
chrome.storage.sync.set({
|
||||
browser.storage.sync.set({
|
||||
theme: theme,
|
||||
blacklist: blacklist,
|
||||
whitelist: whitelist,
|
||||
loggingType: loggingType,
|
||||
loggingStyle: loggingStyle
|
||||
}, function () {
|
||||
}).then(function () {
|
||||
// Set state to be newly entered values.
|
||||
that.setState({
|
||||
theme: theme,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global chrome */
|
||||
/* global browser */
|
||||
|
||||
var React = require("react");
|
||||
var $ = require('jquery');
|
||||
@@ -40,9 +40,9 @@ var Wakatime = React.createClass({
|
||||
|
||||
if (data !== false) {
|
||||
|
||||
chrome.storage.sync.get({
|
||||
browser.storage.sync.get({
|
||||
loggingEnabled: config.loggingEnabled
|
||||
}, function(items) {
|
||||
}).then(function(items) {
|
||||
that.setState({loggingEnabled: items.loggingEnabled});
|
||||
|
||||
if (items.loggingEnabled === true) {
|
||||
@@ -129,7 +129,7 @@ var Wakatime = React.createClass({
|
||||
|
||||
changeExtensionState('notLogging');
|
||||
|
||||
chrome.storage.sync.set({
|
||||
browser.storage.sync.set({
|
||||
loggingEnabled: false
|
||||
});
|
||||
},
|
||||
@@ -141,7 +141,7 @@ var Wakatime = React.createClass({
|
||||
|
||||
changeExtensionState('allGood');
|
||||
|
||||
chrome.storage.sync.set({
|
||||
browser.storage.sync.set({
|
||||
loggingEnabled: true
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/* global chrome */
|
||||
/* global browser */
|
||||
//jshint esnext:true
|
||||
|
||||
var config = {
|
||||
// Extension name
|
||||
name: 'WakaTime',
|
||||
// Extension version
|
||||
version: chrome.app.getDetails().version,
|
||||
version: browser.runtime.getManifest().version,
|
||||
// Time for idle state of the browser
|
||||
// The user is considered idle if there was
|
||||
// no activity in the browser for x seconds
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global chrome */
|
||||
/* global browser */
|
||||
//jshint esnext:true
|
||||
|
||||
var $ = require('jquery');
|
||||
@@ -77,19 +77,19 @@ class WakaTimeCore {
|
||||
* and sends it to WakaTime for logging.
|
||||
*/
|
||||
recordHeartbeat() {
|
||||
chrome.storage.sync.get({
|
||||
browser.storage.sync.get({
|
||||
loggingEnabled: config.loggingEnabled,
|
||||
loggingStyle: config.loggingStyle,
|
||||
blacklist: '',
|
||||
whitelist: ''
|
||||
}, (items) => {
|
||||
}).then((items) => {
|
||||
if (items.loggingEnabled === true) {
|
||||
changeExtensionState('allGood');
|
||||
|
||||
chrome.idle.queryState(config.detectionIntervalInSeconds, (newState) => {
|
||||
browser.idle.queryState(config.detectionIntervalInSeconds).then((newState) => {
|
||||
if (newState === 'active') {
|
||||
// Get current tab URL.
|
||||
chrome.tabs.query({active: true}, (tabs) => {
|
||||
browser.tabs.query({active: true}).then((tabs) => {
|
||||
|
||||
var currentActiveTab = tabs[0];
|
||||
var debug = false;
|
||||
@@ -193,7 +193,7 @@ class WakaTimeCore {
|
||||
time: moment().format('X'),
|
||||
project: heartbeat.project || '<<LAST_PROJECT>>',
|
||||
is_debugging: debug,
|
||||
plugin: 'chrome-wakatime/' + config.version
|
||||
plugin: 'browser-wakatime/' + config.version
|
||||
});
|
||||
}
|
||||
|
||||
@@ -207,9 +207,9 @@ class WakaTimeCore {
|
||||
_getLoggingType() {
|
||||
var deferredObject = $.Deferred();
|
||||
|
||||
chrome.storage.sync.get({
|
||||
browser.storage.sync.get({
|
||||
loggingType: config.loggingType
|
||||
}, function (items) {
|
||||
}).then(function (items) {
|
||||
deferredObject.resolve(items.loggingType);
|
||||
});
|
||||
|
||||
@@ -284,4 +284,4 @@ class WakaTimeCore {
|
||||
|
||||
}
|
||||
|
||||
export default WakaTimeCore;
|
||||
//export default WakaTimeCore;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* global chrome */
|
||||
/* global browser */
|
||||
|
||||
// Create a connection to the background page
|
||||
var backgroundPageConnection = chrome.runtime.connect({
|
||||
var backgroundPageConnection = browser.runtime.connect({
|
||||
name: "devtools-page"
|
||||
});
|
||||
|
||||
// Send a message to background page with the current active tabId
|
||||
backgroundPageConnection.postMessage({
|
||||
name: 'init',
|
||||
tabId: chrome.devtools.inspectedWindow.tabId
|
||||
tabId: browser.devtools.inspectedWindow.tabId
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global chrome */
|
||||
/* global browser */
|
||||
|
||||
// Core
|
||||
var WakaTimeCore = require("./core/WakaTimeCore").default;
|
||||
@@ -11,7 +11,7 @@ var wakatime = new WakaTimeCore();
|
||||
var connections = {};
|
||||
|
||||
// Add a listener to resolve alarms
|
||||
chrome.alarms.onAlarm.addListener(function (alarm) {
|
||||
browser.alarms.onAlarm.addListener(function (alarm) {
|
||||
// |alarm| can be undefined because onAlarm also gets called from
|
||||
// window.setTimeout on old chrome versions.
|
||||
if (alarm && alarm.name == 'heartbeatAlarm') {
|
||||
@@ -23,14 +23,14 @@ chrome.alarms.onAlarm.addListener(function (alarm) {
|
||||
});
|
||||
|
||||
// Create a new alarm for heartbeats.
|
||||
chrome.alarms.create('heartbeatAlarm', {periodInMinutes: 2});
|
||||
browser.alarms.create('heartbeatAlarm', {periodInMinutes: 2});
|
||||
|
||||
/**
|
||||
* Whenever a active tab is changed it records a heartbeat with that tab url.
|
||||
*/
|
||||
chrome.tabs.onActivated.addListener(function (activeInfo) {
|
||||
browser.tabs.onActivated.addListener(function (activeInfo) {
|
||||
|
||||
chrome.tabs.get(activeInfo.tabId, function (tab) {
|
||||
browser.tabs.get(activeInfo.tabId).then(function (tab) {
|
||||
|
||||
console.log('recording a heartbeat - active tab changed');
|
||||
|
||||
@@ -43,11 +43,11 @@ chrome.tabs.onActivated.addListener(function (activeInfo) {
|
||||
* Whenever any tab is updated it checks if the updated tab is the tab that is
|
||||
* currently active and if it is, then it records a heartbeat.
|
||||
*/
|
||||
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
|
||||
browser.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
|
||||
|
||||
if (changeInfo.status === 'complete') {
|
||||
// Get current tab URL.
|
||||
chrome.tabs.query({active: true}, function(tabs) {
|
||||
browser.tabs.query({active: true}).then(function(tabs) {
|
||||
// If tab updated is the same as active tab
|
||||
if (tabId == tabs[0].id) {
|
||||
console.log('recording a heartbeat - tab updated');
|
||||
@@ -64,7 +64,7 @@ chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
|
||||
* This is in charge of detecting if devtools are opened or closed
|
||||
* and sending a heartbeat depending on that.
|
||||
*/
|
||||
chrome.runtime.onConnect.addListener(function (port) {
|
||||
browser.runtime.onConnect.addListener(function (port) {
|
||||
|
||||
if (port.name == "devtools-page") {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global chrome */
|
||||
/* global browser */
|
||||
|
||||
var config = require('../config');
|
||||
|
||||
@@ -19,26 +19,26 @@ function changeExtensionIcon(color) {
|
||||
|
||||
path = './graphics/wakatime-logo-38' + color + '.png';
|
||||
|
||||
chrome.browserAction.setIcon({
|
||||
browser.browserAction.setIcon({
|
||||
path: path
|
||||
});
|
||||
}
|
||||
|
||||
if (color === '') {
|
||||
chrome.storage.sync.get({
|
||||
browser.storage.sync.get({
|
||||
theme: config.theme
|
||||
}, function (items) {
|
||||
}).then(function (items) {
|
||||
if (items.theme == config.theme) {
|
||||
path = './graphics/wakatime-logo-38.png';
|
||||
|
||||
chrome.browserAction.setIcon({
|
||||
browser.browserAction.setIcon({
|
||||
path: path
|
||||
});
|
||||
}
|
||||
else {
|
||||
path = './graphics/wakatime-logo-38-white.png';
|
||||
|
||||
chrome.browserAction.setIcon({
|
||||
browser.browserAction.setIcon({
|
||||
path: path
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global chrome */
|
||||
/* global browser */
|
||||
|
||||
var config = require('../config');
|
||||
|
||||
@@ -16,7 +16,7 @@ function changeExtensionTooltip(text) {
|
||||
text = config.name + ' - ' + text;
|
||||
}
|
||||
|
||||
chrome.browserAction.setTitle({title: text});
|
||||
browser.browserAction.setTitle({title: text});
|
||||
}
|
||||
|
||||
module.exports = changeExtensionTooltip;
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global chrome */
|
||||
/* global browser */
|
||||
|
||||
/* This is a fix for Bootstrap requiring jQuery */
|
||||
global.jQuery = require('jquery');
|
||||
|
||||
4
assets/less/bootstrap/bootstrap.less
vendored
4
assets/less/bootstrap/bootstrap.less
vendored
@@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap v3.3.6 (http://getbootstrap.com)
|
||||
* Copyright 2011-2015 Twitter, Inc.
|
||||
* Bootstrap v3.3.7 (http://getbootstrap.com)
|
||||
* Copyright 2011-2016 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
.border-right-radius(0);
|
||||
}
|
||||
}
|
||||
// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it
|
||||
// Need .dropdown-toggle since :last-child doesn't apply, given that a .dropdown-menu is used immediately after it
|
||||
.btn-group > .btn:last-child:not(:first-child),
|
||||
.btn-group > .dropdown-toggle:not(:first-child) {
|
||||
.border-left-radius(0);
|
||||
|
||||
@@ -181,7 +181,7 @@ input[type="search"] {
|
||||
// set a pixel line-height that matches the given height of the input, but only
|
||||
// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848
|
||||
//
|
||||
// Note that as of 8.3, iOS doesn't support `datetime` or `week`.
|
||||
// Note that as of 9.3, iOS doesn't support `week`.
|
||||
|
||||
@media screen and (-webkit-min-device-pixel-ratio: 0) {
|
||||
input[type="date"],
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
width: 100%;
|
||||
margin-bottom: 0;
|
||||
|
||||
|
||||
&:focus {
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// WebKit-style focus
|
||||
|
||||
.tab-focus() {
|
||||
// Default
|
||||
outline: thin dotted;
|
||||
// WebKit
|
||||
// WebKit-specific. Other browsers will keep their default outline style.
|
||||
// (Initially tried to also force default via `outline: initial`,
|
||||
// but that seems to erroneously remove the outline in Firefox altogether.)
|
||||
outline: 5px auto -webkit-focus-ring-color;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@
|
||||
}
|
||||
|
||||
|
||||
// Collapsable panels (aka, accordion)
|
||||
// Collapsible panels (aka, accordion)
|
||||
//
|
||||
// Wrap a series of panels in `.panel-group` to turn them into an accordion with
|
||||
// the help of our collapse JavaScript plugin.
|
||||
|
||||
@@ -120,7 +120,7 @@ hr {
|
||||
|
||||
// Only display content to screen readers
|
||||
//
|
||||
// See: http://a11yproject.com/posts/how-to-hide-content/
|
||||
// See: http://a11yproject.com/posts/how-to-hide-content
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* Bootstrap v3.3.6 (http://getbootstrap.com)
|
||||
* Copyright 2011-2015 Twitter, Inc.
|
||||
* Bootstrap v3.3.7 (http://getbootstrap.com)
|
||||
* Copyright 2011-2016 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
//** Global background color for active items (e.g., navs or dropdowns).
|
||||
@component-active-bg: @brand-primary;
|
||||
|
||||
//** Width of the `border` for generating carets that indicator dropdowns.
|
||||
//** Width of the `border` for generating carets that indicate dropdowns.
|
||||
@caret-width-base: 4px;
|
||||
//** Carets increase slightly in size for larger components.
|
||||
@caret-width-large: 5px;
|
||||
|
||||
20
gulpfile.js
20
gulpfile.js
@@ -1,6 +1,8 @@
|
||||
var del = require('del');
|
||||
var gulp = require('gulp');
|
||||
var elixir = require('laravel-elixir');
|
||||
var exec = require('child_process').exec;
|
||||
var fs = require('fs');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -16,6 +18,15 @@ gulp.task('postinstall', function (cb) {
|
||||
//so we remove them on postinstall
|
||||
del('node_modules/**/*.pem', cb);
|
||||
});
|
||||
gulp.task('webextension',function(cb){
|
||||
exec('npm install',{
|
||||
cwd: 'node_modules/webextension-polyfill/'
|
||||
},function(){
|
||||
var stream = fs.createWriteStream('public/js/browser-polyfill.min.js');
|
||||
stream.on('done',cb);
|
||||
fs.createReadStream('node_modules/webextension-polyfill/dist/browser-polyfill.min.js').pipe(stream);
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -30,14 +41,19 @@ gulp.task('postinstall', function (cb) {
|
||||
|
||||
elixir.config.assetsPath = 'assets/';
|
||||
|
||||
elixir.extend('webextension', function(){
|
||||
return gulp.start('webextension');
|
||||
});
|
||||
|
||||
elixir(function (mix) {
|
||||
mix.webextension();
|
||||
mix.copy('vendor/bower_components/bootstrap/less', 'assets/less/bootstrap');
|
||||
mix.copy('vendor/bower_components/bootstrap/fonts', 'public/fonts');
|
||||
/*mix.copy('vendor/bower_components/bootstrap/fonts', 'public/fonts');
|
||||
mix.copy('vendor/bower_components/font-awesome/less', 'assets/less/font-awesome');
|
||||
mix.copy('vendor/bower_components/font-awesome/fonts', 'public/fonts');
|
||||
mix.less('app.less');
|
||||
mix.browserify('app.jsx', 'public/js/app.js', 'assets/js');
|
||||
mix.browserify('events.js', 'public/js/events.js', 'assets/js');
|
||||
mix.browserify('options.jsx', 'public/js/options.js', 'assets/js');
|
||||
mix.browserify('devtools.js', 'public/js/devtools.js', 'assets/js');
|
||||
mix.browserify('devtools.js', 'public/js/devtools.js', 'assets/js');*/
|
||||
});
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
],
|
||||
"background": {
|
||||
"scripts": [
|
||||
"public/js/browser-polyfill.min.js",
|
||||
"public/js/events.js"
|
||||
],
|
||||
"persistent": false
|
||||
@@ -35,5 +36,10 @@
|
||||
"options_ui": {
|
||||
"page": "options.html",
|
||||
"chrome_style": false
|
||||
},
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "addon@wakatime.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,8 @@
|
||||
"moment": "^2.13.0",
|
||||
"react": "^16.2.0",
|
||||
"react-addons-css-transition-group": "^15.1.0",
|
||||
"react-dom": "^16.2.0"
|
||||
"react-dom": "^16.2.0",
|
||||
"webextension-polyfill": "^0.2.1"
|
||||
},
|
||||
"jshintConfig": {
|
||||
"asi": false,
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<title>WakaTime</title>
|
||||
|
||||
<link href="public/css/app.css" rel="stylesheet">
|
||||
<script src="public/js/browser-polyfill.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var chai = require('chai');
|
||||
var expect = chai.expect;
|
||||
|
||||
import changeExtensionIcon from '../../assets/js/helpers/changeExtensionIcon';
|
||||
//import changeExtensionIcon from '../../assets/js/helpers/changeExtensionIcon';
|
||||
|
||||
describe('changeExtensionIcon', function() {
|
||||
it('should be a function', function() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var chai = require('chai');
|
||||
var expect = chai.expect;
|
||||
|
||||
import changeExtensionState from '../../assets/js/helpers/changeExtensionState';
|
||||
//import changeExtensionState from '../../assets/js/helpers/changeExtensionState';
|
||||
|
||||
describe('changeExtensionState', function() {
|
||||
it('should be a function', function() {
|
||||
|
||||
@@ -3,7 +3,7 @@ var sinon = require('sinon-chai');
|
||||
var chrome = require('sinon-chrome');
|
||||
var expect = chai.expect;
|
||||
|
||||
import changeExtensionTooltip from '../../assets/js/helpers/changeExtensionTooltip';
|
||||
//import changeExtensionTooltip from '../../assets/js/helpers/changeExtensionTooltip';
|
||||
|
||||
describe('changeExtensionTooltip', function() {
|
||||
it('should be a function', function() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var chai = require('chai');
|
||||
var expect = chai.expect;
|
||||
|
||||
import contains from '../../assets/js/helpers/contains';
|
||||
//import contains from '../../assets/js/helpers/contains';
|
||||
|
||||
describe('contains', function() {
|
||||
it('should be a function', function() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var chai = require('chai');
|
||||
var expect = chai.expect;
|
||||
|
||||
import getDomainFromUrl from '../../assets/js/helpers/getDomainFromUrl';
|
||||
//import getDomainFromUrl from '../../assets/js/helpers/getDomainFromUrl';
|
||||
|
||||
describe('getDomainFromUrl', function() {
|
||||
it('should be a function', function() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var chai = require('chai');
|
||||
var expect = chai.expect;
|
||||
|
||||
import in_array from '../../assets/js/helpers/in_array';
|
||||
//import in_array from '../../assets/js/helpers/in_array';
|
||||
|
||||
describe('in_array', function() {
|
||||
it('should be a function', function() {
|
||||
|
||||
Reference in New Issue
Block a user