diff --git a/README.md b/README.md
index 338e5af9..c47ff1ce 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,11 @@ Note: Activity from this Chrome extension will not display on leaderboards, so i
1. Install the extension:
-[![Chrome Web Store](https://wakatime.com/static/img/chrome-web-store.png)](https://chrome.google.com/webstore/detail/wakatime/jnbbnacmeggbgdjgaoojpmhdlkkpblgi)
+[![Chrome](https://wakatime.com/static/img/chrome-web-store.png)](https://chrome.google.com/webstore/detail/wakatime/jnbbnacmeggbgdjgaoojpmhdlkkpblgi)
+
+[![Firefox](https://wakatime.com/static/img/firefox-addon.png)](https://addons.mozilla.org/en-US/firefox/addon/wakatime/)
+
+[![Edge](https://wakatime.com/static/img/microsoft-extension.png)](https://microsoftedge.microsoft.com/addons/detail/wakatime/cdnpfnaadjmaplhghnlonephmabegadl)
2. Login to [WakaTime](https://wakatime.com/).
diff --git a/src/background.ts b/src/background.ts
index f652d34d..0eb455a7 100644
--- a/src/background.ts
+++ b/src/background.ts
@@ -1,5 +1,6 @@
import browser from 'webextension-polyfill';
import WakaTimeCore from './core/WakaTimeCore';
+import { PostHeartbeatMessage } from './types/heartbeats';
// Add a listener to resolve alarms
browser.alarms.onAlarm.addListener(async (alarm) => {
@@ -22,7 +23,7 @@ browser.alarms.create('heartbeatAlarm', { periodInMinutes: 2 });
* Whenever a active tab is changed it records a heartbeat with that tab url.
*/
browser.tabs.onActivated.addListener(async () => {
- console.log('recording a heartbeat - active tab changed ');
+ console.log('recording a heartbeat - active tab changed');
await WakaTimeCore.recordHeartbeat();
});
@@ -62,6 +63,12 @@ self.addEventListener('activate', async () => {
await WakaTimeCore.createDB();
});
+browser.runtime.onMessage.addListener(async (request: PostHeartbeatMessage) => {
+ if (request.recordHeartbeat === true) {
+ await WakaTimeCore.recordHeartbeat(request.projectDetails);
+ }
+});
+
/**
* "Persistent" service worker via bug exploit
* https://stackoverflow.com/questions/66618136/persistent-service-worker-in-chrome-extension
diff --git a/src/components/Options.tsx b/src/components/Options.tsx
index ec3c0312..e2d7e6fb 100644
--- a/src/components/Options.tsx
+++ b/src/components/Options.tsx
@@ -308,9 +308,9 @@ export default function Options(): JSX.Element {
className="form-control"
value={state.apiUrl}
onChange={(e) => setState({ ...state, apiUrl: e.target.value })}
- placeholder="https://wakatime.com/api/v1"
+ placeholder="https://api.wakatime.com/api/v1"
/>
- https://wakatime.com/api/v1
+ https://api.wakatime.com/api/v1
diff --git a/src/config/config.test.ts b/src/config/config.test.ts
index 7987e4b0..7d357eb5 100644
--- a/src/config/config.test.ts
+++ b/src/config/config.test.ts
@@ -25,7 +25,7 @@ describe('wakatime config', () => {
},
},
"apiKey": "",
- "apiUrl": "https://wakatime.com/api/v1",
+ "apiUrl": "https://api.wakatime.com/api/v1",
"colors": {
"allGood": "",
"lightTheme": "white",
diff --git a/src/config/config.ts b/src/config/config.ts
index 1f24c91a..f10f19c5 100644
--- a/src/config/config.ts
+++ b/src/config/config.ts
@@ -120,7 +120,7 @@ const config: Config = {
apiKey: '',
- apiUrl: process.env.API_URL ?? 'https://wakatime.com/api/v1',
+ apiUrl: process.env.API_URL ?? 'https://api.wakatime.com/api/v1',
colors: {
allGood: '',
diff --git a/src/core/WakaTimeCore.ts b/src/core/WakaTimeCore.ts
index 321ad46a..1d699316 100644
--- a/src/core/WakaTimeCore.ts
+++ b/src/core/WakaTimeCore.ts
@@ -354,6 +354,7 @@ class WakaTimeCore {
};
payload.project = heartbeat.project ?? '<>';
+ payload.branch = heartbeat.branch ?? '<>';
return payload;
}
diff --git a/src/manifests/chrome.json b/src/manifests/chrome.json
index 3d7d131b..58aad161 100644
--- a/src/manifests/chrome.json
+++ b/src/manifests/chrome.json
@@ -33,5 +33,5 @@
"page": "options.html"
},
"permissions": ["alarms", "tabs", "storage", "idle"],
- "version": "3.0.17"
+ "version": "3.0.21"
}
diff --git a/src/manifests/edge.json b/src/manifests/edge.json
new file mode 100644
index 00000000..34ad2d9f
--- /dev/null
+++ b/src/manifests/edge.json
@@ -0,0 +1,37 @@
+{
+ "action": {
+ "default_icon": {
+ "19": "graphics/wakatime-logo-19.png",
+ "38": "graphics/wakatime-logo-38.png"
+ },
+ "default_popup": "popup.html",
+ "default_title": "WakaTime"
+ },
+ "background": {
+ "service_worker": "background.js",
+ "type": "module"
+ },
+ "content_scripts": [
+ {
+ "matches": [""],
+ "js": ["wakatimeScript.js"],
+ "run_at": "document_end"
+ }
+ ],
+ "description": "Automatic time tracking for Edge.",
+ "devtools_page": "devtools.html",
+ "homepage_url": "https://wakatime.com",
+ "host_permissions": ["https://api.wakatime.com/*", "https://wakatime.com/*"],
+ "icons": {
+ "16": "graphics/wakatime-logo-16.png",
+ "48": "graphics/wakatime-logo-48.png",
+ "128": "graphics/wakatime-logo-128.png"
+ },
+ "manifest_version": 3,
+ "name": "WakaTime",
+ "options_ui": {
+ "page": "options.html"
+ },
+ "permissions": ["alarms", "tabs", "storage", "idle"],
+ "version": "3.0.21"
+}
diff --git a/src/manifests/firefox.json b/src/manifests/firefox.json
index f3170357..30a57bb3 100644
--- a/src/manifests/firefox.json
+++ b/src/manifests/firefox.json
@@ -39,5 +39,5 @@
"page": "options.html"
},
"permissions": ["", "alarms", "tabs", "storage", "idle"],
- "version": "3.0.17"
+ "version": "3.0.21"
}
diff --git a/src/types/heartbeats.ts b/src/types/heartbeats.ts
index f418e0d2..69734144 100644
--- a/src/types/heartbeats.ts
+++ b/src/types/heartbeats.ts
@@ -28,7 +28,20 @@ export interface Datum {
}
export interface SendHeartbeat {
+ branch: string | null;
hostname: string;
project: string | null;
url: string;
}
+
+export interface ProjectDetails {
+ category: string;
+ editor: string;
+ language: string;
+ project: string;
+}
+
+export interface PostHeartbeatMessage {
+ projectDetails?: ProjectDetails;
+ recordHeartbeat: boolean;
+}
diff --git a/src/types/user.ts b/src/types/user.ts
index c5edc51c..860e899e 100644
--- a/src/types/user.ts
+++ b/src/types/user.ts
@@ -25,10 +25,11 @@ export interface User {
is_hireable: boolean;
is_onboarding_finished: boolean;
languages_used_public: boolean;
+ last_branch?: string;
last_heartbeat_at: string;
last_plugin: string;
last_plugin_name: string;
- last_project: string;
+ last_project?: string;
location: string;
logged_time_public: boolean;
modified_at: string;
diff --git a/src/wakatimeScript.ts b/src/wakatimeScript.ts
index 028fec21..63649fbc 100644
--- a/src/wakatimeScript.ts
+++ b/src/wakatimeScript.ts
@@ -1,5 +1,3 @@
-import WakaTimeCore from './core/WakaTimeCore';
-
const twoMinutes = 120000;
interface DesignProject {
@@ -10,13 +8,18 @@ interface DesignProject {
}
const parseCanva = (): DesignProject | undefined => {
- const canvaProject = document.getElementsByClassName('rF765A');
- if (canvaProject.length === 0) return;
-
const projectName = (document.head.querySelector('meta[property="og:title"]') as HTMLMetaElement)
.content;
+ if (!projectName) return;
+
+ // make sure the page title matches the design input element's value, meaning this is a design file
+ const canvaProjectInput = Array.from(
+ document.querySelector('nav')?.querySelectorAll('input') ?? [],
+ ).find((inp) => inp.value === projectName);
+ if (!canvaProjectInput) return;
+
return {
- category: 'Designing',
+ category: 'designing',
editor: 'Canva',
language: 'Canva Design',
project: projectName,
@@ -30,7 +33,7 @@ const parseFigma = (): DesignProject | undefined => {
const projectName = (document.querySelector('span[data-testid="filename"]') as HTMLElement)
.innerText;
return {
- category: 'Designing',
+ category: 'designing',
editor: 'Figma',
language: 'Figma Design',
project: projectName,
@@ -50,9 +53,8 @@ const init = async () => {
const { hostname } = document.location;
const projectDetails = getParser[hostname]?.();
-
if (projectDetails) {
- await WakaTimeCore.recordHeartbeat(projectDetails);
+ chrome.runtime.sendMessage({ projectDetails, recordHeartbeat: true });
}
};
diff --git a/webpack.config.ts b/webpack.config.ts
index 42f180dc..51a99e07 100644
--- a/webpack.config.ts
+++ b/webpack.config.ts
@@ -4,7 +4,7 @@ import * as webpack from 'webpack';
// eslint-disable-next-line
import CopyPlugin from 'copy-webpack-plugin';
-type BrowserTypes = 'chrome' | 'firefox';
+type BrowserTypes = 'chrome' | 'firefox' | 'edge';
const publicFolder = join(__dirname, 'public');
const cssFolder = join(publicFolder, 'css');
@@ -75,5 +75,9 @@ export default (
arv: Record,
): webpack.Configuration[] => {
const isProd = arv.mode !== 'development';
- return [getConfigByBrowser(isProd, 'chrome'), getConfigByBrowser(isProd, 'firefox')];
+ return [
+ getConfigByBrowser(isProd, 'chrome'),
+ getConfigByBrowser(isProd, 'firefox'),
+ getConfigByBrowser(isProd, 'edge'),
+ ];
};