Skip to content

Commit

Permalink
Merge pull request #29 from Tech-Nest-Ventures/21-not-sending-daily-e…
Browse files Browse the repository at this point in the history
…mailsweekly-summary-emails

21 not sending daily emailsweekly summary emails
  • Loading branch information
timeowilliams authored Nov 3, 2024
2 parents 88a88dc + 661e83b commit 1692d29
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 153 deletions.
2 changes: 1 addition & 1 deletion latest-mac.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"url": "https://github.com/Tech-Nest-Ventures/deepFocus/releases/download/v.2.4.4/Deep.Focus.zip",
"url": "https://github.com/Tech-Nest-Ventures/deepFocus/releases/download/v2.4.4/Deep.Focus.zip",
"name": "2.4.4",
"notes": "Bug fixes and performance improvements.",
"pub_date": "2024-11-02T12:00:00Z"
Expand Down
60 changes: 60 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -652,3 +652,63 @@ export function handleDailyReset() {
}
}
}

async function sendDailyEmail(username, date, deepWorkHours, siteTimeTrackers) {
if (!username || siteTimeTrackers.length === 0) {
console.log('No data to send in email.')
return
}

const MIN_TIME_THRESHOLD = 60
const filteredTrackers = siteTimeTrackers.filter(
(tracker) => tracker.timeSpent >= MIN_TIME_THRESHOLD
)

const emailData = {
username,
date,
deepWorkHours,
trackers: filteredTrackers.map((tracker) => ({
title: tracker.title,
url: tracker.url,
timeSpent: tracker.timeSpent
}))
}

try {
const response = await fetch(`${process.env.VITE_SERVER_URL_PROD}/api/v1/email/send-daily`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(emailData)
})
console.log('Email sent status:', response.status)
} catch (error) {
console.error('Error sending email:', error)
}
}


async function checkAndSendMissedEmails() {
const lastEmailDate = dayjs(store.get(LAST_EMAIL_DATE_KEY, null) || dayjs().subtract(1, 'day'))
const today = dayjs().startOf('day')

if (!lastEmailDate.isSame(today, 'day')) {
let dateToProcess = lastEmailDate.add(1, 'day')

while (dateToProcess.isBefore(today) || dateToProcess.isSame(today, 'day')) {
const formattedDate = dateToProcess.format('YYYY-MM-DD')
console.log(`Sending missed email for date: ${formattedDate}`)

const username = store.get('user')?.username
const deepWorkHours = store.get('deepWorkHours')
const siteTimeTrackers = store.get('siteTimeTrackers', [])

await sendDailyEmail(username, formattedDate, deepWorkHours, siteTimeTrackers)

// Update the last email date after each successful send
store.set(LAST_EMAIL_DATE_KEY, dateToProcess.toISOString())

dateToProcess = dateToProcess.add(1, 'day')
}
}
}
5 changes: 3 additions & 2 deletions src/productivityUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ export function getActiveWindowApp(): Promise<string | browser> {
export function getBrowserURL(browser: string): Promise<string> {
return new Promise<string>((resolve, _reject) => {
let script = `osascript -e 'tell application "${browser}" to get URL of active tab of front window'`
if (browser === 'Safari') {
if (browser === 'Safari' || browser === 'Orion') {
script = `osascript -e 'tell application "${browser}" to get URL of front document'`
} else if (browser.toLowerCase() === 'firefox') {
script = `
Expand Down Expand Up @@ -249,6 +249,7 @@ export function isBrowser(appName: string): appName is browser {
'Opera',
'Safari',
'Firefox',
'firefox'
'firefox',
'Orion'
].includes(appName)
}
16 changes: 5 additions & 11 deletions src/renderer/src/Analytics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SiteTimeTracker, TrackerType, AppIcon } from './types'
const BarChart = lazy(() => import('./BarChart'))
import { IpcRendererEvent } from 'electron'
import {Motion} from 'solid-motionone';
import { getFavicon } from './lib/utils'

const Analytics = () => {
const [showDeepWork, setShowDeepWork] = createSignal(true) // State for toggle
Expand All @@ -13,26 +14,19 @@ const Analytics = () => {


// Function to fetch the icon data URL
const fetchAppIcon = async (iconPath?: string) => {
const fetchAppIcon = async (iconPath?: string): Promise<string> => {
try {
const iconDataUrl = await window.electron.ipcRenderer.invoke('get-icon', iconPath)
const iconUrl = iconDataUrl || 'https://cdn-icons-png.freepik.com/512/7022/7022186.png'

// Cache the fetched icon
setIconCache({ ...iconCache(), [iconPath]: iconUrl })

return iconUrl
} catch (error) {
console.error('Error fetching app icon:', error)
return 'https://cdn-icons-png.freepik.com/512/7022/7022186.png' // Return default icon on error
}
}

// Function to fetch the favicon for websites
const fetchFavicon = (url: string) => {
return `https://www.google.com/s2/favicons?sz=64&domain=${new URL(url).hostname}`
}

const fetchSiteTrackers = () => {
window?.electron?.ipcRenderer.send('fetch-site-trackers')
}
Expand All @@ -50,12 +44,12 @@ const Analytics = () => {
console.warn('Skipping invalid tracker:', tracker)
return null
}

let iconUrl = ''

if (tracker.type === TrackerType.Website) {
// Fetch the favicon for websites
iconUrl = fetchFavicon(tracker.url)
iconUrl = getFavicon(tracker.url)
} else if (tracker.type === TrackerType.App && tracker.iconUrl) {
// If tracker has a valid iconPath, fetch the app icon
iconUrl = await fetchAppIcon(tracker.iconUrl)
Expand Down
10 changes: 1 addition & 9 deletions src/renderer/src/UnproductiveWebsites.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,12 @@ import { createSignal, For, onMount, onCleanup } from 'solid-js'
import { TextField, TextFieldInput } from './components/ui/text-field'
import { Button } from './components/ui/button'
import { IoRemoveCircleOutline, VsAdd } from './components/ui/icons'
import { getFavicon } from './lib/utils'

const UnproductiveWebsites = () => {
const [site, setSite] = createSignal('')
const [unproductiveSites, setUnproductiveSites] = createSignal<string[]>([])

const getFavicon = (url: string) => {
try {
const domain = new URL(url).hostname
return `https://www.google.com/s2/favicons?domain=${domain}`
} catch (error) {
console.error('Invalid URL format:', url)
return ''
}
}

onMount(() => {
window.electron.ipcRenderer.send('fetch-unproductive-urls') // Request URLs from main process
Expand Down
16 changes: 16 additions & 0 deletions src/renderer/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,19 @@ export const stopActivityMonitoring = () => {
console.log('Stopping activity monitoring')
window?.electron.ipcRenderer.send('logout-user')
}


export const getFavicon = (url: string): string => {
try {
const formattedUrl = url.startsWith('http://') ? url.replace('http://', 'https://') : url
const domain = new URL(formattedUrl).hostname
if (domain === 'mail.google.com') {
return 'https://ssl.gstatic.com/ui/v1/icons/mail/rfr/gmail.ico'
} else {
return `https://www.google.com/s2/favicons?sz=64&domain=${formattedUrl}`
}
} catch (error) {
console.error('Invalid URL format:', url)
return ''
}
}
108 changes: 1 addition & 107 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,110 +53,6 @@ export type DeepWorkHours = {
Saturday: number
Sunday: number
}

export type ExtendedResult = Result & { url?: string; siteTimeTracker?: SiteTimeTracker }

export type Options = {
/**
Enable the accessibility permission check. _(macOS)_
Setting this to `false` will prevent the accessibility permission prompt on macOS versions 10.15 and newer. The `url` property won't be retrieved.
@default true
*/
readonly accessibilityPermission: boolean

/**
Enable the screen recording permission check. _(macOS)_
Setting this to `false` will prevent the screen recording permission prompt on macOS versions 10.15 and newer. The `title` property in the result will always be set to an empty string.
@default true
*/
readonly screenRecordingPermission: boolean
}

export type BaseOwner = {
/**
Name of the app.
*/
name: string

/**
Process identifier
*/
processId: number

/**
Path to the app.
*/
path: string
}

export type BaseResult = {
/**
Window title.
*/
title: string

/**
Window identifier.
On Windows, there isn't a clear notion of a "Window ID". Instead it returns the memory address of the window "handle" in the `id` property. That "handle" is unique per window, so it can be used to identify them. [Read more…](https://msdn.microsoft.com/en-us/library/windows/desktop/ms632597(v=vs.85).aspx#window_handle).
*/
id: number

/**
Window position and size.
*/
bounds: {
x: number
y: number
width: number
height: number
}

/**
App that owns the window.
*/
owner: BaseOwner

/**
Memory usage by the window.
*/
memoryUsage: number
}

// eslint-disable-next-line @typescript-eslint/naming-convention
export type MacOSOwner = {
/**
Bundle identifier.
*/
bundleId: string
} & BaseOwner

// eslint-disable-next-line @typescript-eslint/naming-convention
export type MacOSResult = {
platform: 'macos'

owner: MacOSOwner

/**
URL of the active browser tab if the active window is Safari (includes Technology Preview), Chrome (includes Beta, Dev, and Canary), Edge (includes Beta, Dev, and Canary), Brave (includes Beta and Nightly), Mighty, Ghost Browser, WaveBox, Sidekick, Opera (includes Beta and Developer), or Vivaldi.
*/
url?: string
} & BaseResult

export type LinuxResult = {
platform: 'linux'
} & BaseResult

export type WindowsResult = {
platform: 'windows'
} & BaseResult

export type Result = MacOSResult | LinuxResult | WindowsResult

export interface ElectronAPI {
sendUserData: (user: {
username: string
Expand All @@ -177,20 +73,18 @@ export type browser =
| 'Safari'
| 'Firefox'
| 'firefox'
| 'Orion'

export interface WorkContext {
type: 'URL' | 'appName'
value: string
}



export interface AppIcon {
appName: string
iconPath: string
}


export enum TrackerType {
Website = 'website',
App = 'app'
Expand Down
9 changes: 7 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export function checkForUpdates(): void {
const server = 'https://raw.githubusercontent.com/Tech-Nest-Ventures/deepFocus/main'
const feedURL = `${server}/latest-mac.json`
autoUpdater.setFeedURL({ url: feedURL, serverType: 'json' })

log.info(autoUpdater.getFeedURL())
autoUpdater.checkForUpdates()

Expand All @@ -24,6 +25,10 @@ export function checkForUpdates(): void {
})
})

autoUpdater.on('checking-for-update', () => {
log.info('Checking for update...')
})

autoUpdater.on('update-not-available', () => {
log.info('No update available.')

Expand All @@ -45,8 +50,8 @@ export function checkForUpdates(): void {
})
})

autoUpdater.on('update-downloaded', async () => {
log.info('Update downloaded to:', autoUpdater.getFeedURL())
autoUpdater.on('update-downloaded', async (event, releaseNotes, releaseDate, updateURL) => {
log.info('Update downloaded to:', releaseNotes, releaseDate, updateURL)
const { response } = await dialog.showMessageBox({
type: 'info',
title: 'Install Update',
Expand Down
21 changes: 0 additions & 21 deletions vite.renderer.config.mts.timestamp-1729641953107-ae8ec9be8ef4b.mjs

This file was deleted.

0 comments on commit 1692d29

Please sign in to comment.