diff --git a/src/js/background.js b/src/js/background.js
index 7a72a09..934d4a0 100644
--- a/src/js/background.js
+++ b/src/js/background.js
@@ -11,7 +11,8 @@ function timerStoppedForCurrentService(service, timedActivity) {
return timedActivity.service_id && timedActivity.service_id === service?.id
}
-function resetBubble({ tab, apiClient, service, timedActivity }) {
+function resetBubble({ tab, settings, service, timedActivity }) {
+ const apiClient = new ApiClient(settings)
apiClient
.activitiesStatus(service)
.then(({ data }) => {
@@ -20,6 +21,7 @@ function resetBubble({ tab, apiClient, service, timedActivity }) {
payload: {
bookedSeconds: data.seconds,
timedActivity: data.timed_activity,
+ settingTimeTrackingHHMM: settings.settingTimeTrackingHHMM,
service,
},
})
@@ -58,7 +60,7 @@ chrome.runtime.onMessage.addListener(action => {
const apiClient = new ApiClient(settings)
apiClient
.createActivity(activity)
- .then(() => resetBubble({ tab, apiClient, service }))
+ .then(() => resetBubble({ tab, settings, service }))
.catch(error => {
if (error.response?.status === 422) {
chrome.runtime.sendMessage({
@@ -78,7 +80,7 @@ chrome.runtime.onMessage.addListener(action => {
const apiClient = new ApiClient(settings)
apiClient
.stopTimer(timedActivity)
- .then(() => resetBubble({ tab, apiClient, service, timedActivity }))
+ .then(() => resetBubble({ tab, settings, service, timedActivity }))
.catch(() => null)
})
})
diff --git a/src/js/components/Bubble.js b/src/js/components/Bubble.js
index 9c611b2..da378b7 100644
--- a/src/js/components/Bubble.js
+++ b/src/js/components/Bubble.js
@@ -3,16 +3,19 @@ import PropTypes from "prop-types"
import mocoLogo from "images/moco-32x32.png"
import mocoTimerLogo from "images/moco-timer-32x32.png"
import { parseISO } from "date-fns"
+import { formatDuration } from "utils"
import Timer from "./shared/Timer"
-const Bubble = ({ bookedSeconds, timedActivity }) => {
+const Bubble = ({ bookedSeconds, timedActivity, settingTimeTrackingHHMM }) => {
const logo = timedActivity ? mocoTimerLogo : mocoLogo
return (
})
{!timedActivity && bookedSeconds > 0 && (
-
{(bookedSeconds / 3600).toFixed(2)}
+
+ {formatDuration(bookedSeconds, { settingTimeTrackingHHMM, showSeconds: false })}
+
)}
{timedActivity && (
{
this.isSuccess = false
this.errorMessage = null
- setStorage({ subdomain: this.subdomain, apiKey: this.apiKey }).then(() => {
+ setStorage({
+ subdomain: this.subdomain,
+ apiKey: this.apiKey,
+ settingTimeTrackingHHMM: false,
+ }).then(() => {
const { version } = chrome.runtime.getManifest()
const apiClient = new ApiClient({
subdomain: this.subdomain,
@@ -34,6 +38,9 @@ class Options extends Component {
})
apiClient
.login()
+ .then(({ data }) =>
+ setStorage({ settingTimeTrackingHHMM: data.setting_time_tracking_hh_mm }),
+ )
.then(() => {
this.isSuccess = true
this.closeWindow()
diff --git a/src/js/components/shared/Timer.js b/src/js/components/shared/Timer.js
index f454821..1643883 100644
--- a/src/js/components/shared/Timer.js
+++ b/src/js/components/shared/Timer.js
@@ -1,7 +1,8 @@
import React, { useState } from "react"
import PropTypes from "prop-types"
import { useInterval } from "./hooks"
-import { differenceInSeconds, addSeconds, startOfDay, format } from "date-fns"
+import { differenceInSeconds } from "date-fns"
+import { formatDuration } from "utils"
Timer.propTypes = {
startedAt: PropTypes.instanceOf(Date).isRequired,
@@ -22,7 +23,7 @@ function Timer({ startedAt, offset = 0, onTick, ...domProps }) {
function formattedTimerLabel(startedAt, offset) {
const seconds = differenceInSeconds(new Date(), startedAt) + offset
- return format(addSeconds(startOfDay(new Date()), seconds), "HH:mm:ss")
+ return formatDuration(seconds)
}
export default Timer
diff --git a/src/js/content.js b/src/js/content.js
index 609bb16..04f6075 100644
--- a/src/js/content.js
+++ b/src/js/content.js
@@ -25,7 +25,7 @@ chrome.runtime.onConnect.addListener(function(port) {
document.removeEventListener("click", clickHandler, true)
})
- function updateBubble({ service, bookedSeconds, timedActivity } = {}) {
+ function updateBubble({ service, bookedSeconds, settingTimeTrackingHHMM, timedActivity } = {}) {
if (!document.getElementById("moco-bx-root")) {
const domRoot = document.createElement("div")
domRoot.setAttribute("id", "moco-bx-root")
@@ -50,6 +50,7 @@ chrome.runtime.onConnect.addListener(function(port) {
diff --git a/src/js/utils/browser.js b/src/js/utils/browser.js
index 753bb08..985fbea 100644
--- a/src/js/utils/browser.js
+++ b/src/js/utils/browser.js
@@ -5,7 +5,7 @@ export const isFirefox = () => typeof browser !== "undefined" && chrome
const DEFAULT_SUBDOMAIN = "unset"
export const getSettings = (withDefaultSubdomain = true) => {
- const keys = ["subdomain", "apiKey"]
+ const keys = ["subdomain", "apiKey", "settingTimeTrackingHHMM"]
const { version } = chrome.runtime.getManifest()
if (isChrome()) {
return new Promise(resolve => {
diff --git a/src/js/utils/index.js b/src/js/utils/index.js
index ed85ba1..89ac2c6 100644
--- a/src/js/utils/index.js
+++ b/src/js/utils/index.js
@@ -12,6 +12,7 @@ import {
pick,
head,
defaultTo,
+ padCharsStart,
} from "lodash/fp"
import { startOfWeek, endOfWeek } from "date-fns"
import { format } from "date-fns"
@@ -123,3 +124,22 @@ export const extractAndSetTag = changeset => {
tag: match[1],
}
}
+
+export const formatDuration = (
+ durationInSeconds,
+ { settingTimeTrackingHHMM = true, showSeconds = true } = {},
+) => {
+ if (settingTimeTrackingHHMM) {
+ const hours = Math.floor(durationInSeconds / 3600)
+ const minutes = Math.floor((durationInSeconds % 3600) / 60)
+ const result = `${hours}:${padCharsStart("0", 2, minutes)}`
+ if (!showSeconds) {
+ return result
+ } else {
+ const seconds = durationInSeconds % 60
+ return result + `:${padCharsStart("0", 2, seconds)}`
+ }
+ } else {
+ return (durationInSeconds / 3600).toFixed(2)
+ }
+}
diff --git a/src/js/utils/messageHandlers.js b/src/js/utils/messageHandlers.js
index 480ece9..705de4b 100644
--- a/src/js/utils/messageHandlers.js
+++ b/src/js/utils/messageHandlers.js
@@ -10,7 +10,7 @@ import {
import { get, forEach, reject, isNil } from "lodash/fp"
import { createMatcher } from "utils/urlMatcher"
import remoteServices from "remoteServices"
-import { queryTabs, isBrowserTab, getSettings } from "utils/browser"
+import { queryTabs, isBrowserTab, getSettings, setStorage } from "utils/browser"
const matcher = createMatcher(remoteServices)
@@ -31,6 +31,7 @@ export function tabUpdated(tab, { messenger, settings }) {
type: "showBubble",
payload: {
bookedSeconds: data.seconds,
+ settingTimeTrackingHHMM: settings.settingTimeTrackingHHMM,
timedActivity: data.timed_activity,
service,
},
@@ -41,6 +42,7 @@ export function tabUpdated(tab, { messenger, settings }) {
type: "showBubble",
payload: {
bookedSeconds: 0,
+ settingTimeTrackingHHMM: settings.settingTimeTrackingHHMM,
service,
},
})
@@ -97,6 +99,9 @@ export async function openPopup(tab, { service, messenger }) {
)
}
+ const settingTimeTrackingHHMM = get("[0].data.setting_time_tracking_hh_mm", responses)
+ !isNil(settingTimeTrackingHHMM) && setStorage({ settingTimeTrackingHHMM })
+
const action = {
type: "openPopup",
payload: {
diff --git a/test/utils/index.test.js b/test/utils/index.test.js
index 01fcffe..156bdf7 100644
--- a/test/utils/index.test.js
+++ b/test/utils/index.test.js
@@ -6,6 +6,7 @@ import {
defaultTask,
groupedProjectOptions,
extractAndSetTag,
+ formatDuration,
} from "../../src/js/utils"
import { map, compose } from "lodash/fp"
@@ -142,4 +143,21 @@ describe("utils", () => {
expect(extractAndSetTag(changeset)).toEqual(changeset)
})
})
+
+ describe("formatDuration", () => {
+ it("format with defaults", () => {
+ expect(formatDuration(3600)).toBe("1:00:00")
+ expect(formatDuration(3661)).toBe("1:01:01")
+ })
+
+ it("format without seconds", () => {
+ expect(formatDuration(3600, { showSeconds: false })).toBe("1:00")
+ expect(formatDuration(3661, { showSeconds: false })).toBe("1:01")
+ })
+
+ it("format in decimals", () => {
+ expect(formatDuration(3600, { settingTimeTrackingHHMM: false })).toBe("1.00")
+ expect(formatDuration(3661, { settingTimeTrackingHHMM: false })).toBe("1.02")
+ })
+ })
})