Skip to content

Commit

Permalink
Merge pull request #15 from Tech-Nest-Ventures/add-icons
Browse files Browse the repository at this point in the history
style: added icons
  • Loading branch information
timeowilliams authored Oct 15, 2024
2 parents 69e012e + 882cb0a commit 844885f
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 146 deletions.
10 changes: 2 additions & 8 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,8 @@ jobs:
brew install pkg-config
brew install python3
- name: Install pnpm
run: npm install -g pnpm

- name: Install dependencies
run: pnpm install

- name: Rebuild native modules for Electron
run: pnpm build:mac
run: npm install

- name: Run Playwright tests
run: pnpm test:e2e
run: npm run test:e2e
22 changes: 16 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

> Building the Oura for productivity. Get insights on how productive you are.
Primarily for MacOS. Coming to Windows & Linux shortly.

## Table of Contents

- [Features](#features)
Expand Down Expand Up @@ -77,6 +79,7 @@ Note, for running this app locally, you may run into issues with active-window.
- [ ] Implement secure user authentication system
- [ ] Collect each site visited. Show users all sites visited in the past day at the end of the day/next day and ask them to label them as productive or unproductive.
- [ ] To do list like functionality? Have people add tasks to their list and mark as productive or not productive. Then, at the end of the day, they can see a list of tasks and see how productive they were.
- [] Add toast components.

## Philosophy

Expand All @@ -103,10 +106,17 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file

Timeo Williams [@timeowilliams](https://twitter.com/timeowilliams) - [email protected]

Current Issues:
## Troubleshooting

1. Manually Open the Application
When macOS shows the “developer cannot be verified” error, you can bypass this warning by manually opening the app.

Right-click on the Deep Focus app in the Applications folder.
Select Open.
You should see the same warning message, but this time there will be an Open button to proceed with opening the app.
This will whitelist the app for future use.

2. pnpm (not supported)
We saw some issues with how pnpm was bundling dependencies in the electron-builder stage and it's inability to target certain architectures. We recommend using npm for now.

1. Need to persist Activity Data to backend properly.
2. Right now, I have 5 separate instances of VSCode open. But my logic for time tracking is adding all 5 instances together.
3. Test signing a basic electron app > and then running it locally.
4. I found it interesting how rize-io didnt really do the whole asar unpack thing, but instead had the entire app in a single folder.
5. Fix mocha tests for testing delay.
3. Signing the app
7 changes: 3 additions & 4 deletions electron-builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extraResources:
- from: './resources/icon.png'
to: 'resources/icon.png'

compression: 'store' # Change to 'maximum' to enable compression in PROD. store can reduce build time significantly.
compression: 'maximum' # Change to 'maximum' to enable compression in PROD. store can reduce build time significantly.

asar: true
# This section handles which files are not to be packed into the asar archive and need signing
Expand All @@ -36,7 +36,6 @@ mac:
darkModeSupport: true
hardenedRuntime: true
notarize: false
identity: null
target:
- dmg
extendInfo:
Expand All @@ -52,5 +51,5 @@ appImage:

npmRebuild: true

# afterSign: scripts/signBinaries.js
# afterAllArtifactBuild: scripts/notarize.js
afterSign: scripts/signBinaries.js
afterAllArtifactBuild: scripts/notarize.js
80 changes: 43 additions & 37 deletions src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,14 @@ import dayjs from 'dayjs'
import fs from 'fs'
import dotenv from 'dotenv'
import Store from 'electron-store'
import {
StoreSchema,
SiteTimeTracker,
DeepWorkHours,
MessageType,
User,
Result,
browser
} from './types'
import { StoreSchema, SiteTimeTracker, DeepWorkHours, MessageType, User, browser } from './types'
import {
updateSiteTimeTracker,
isDeepWork,
getBrowserURL,
checkAndRequestPermissions,
getActiveWindowApp
getActiveWindowApp,
getBaseURL
} from './productivityUtils'
import { getInstalledApps } from './childProcess'
import { resetCounters } from './utils'
Expand Down Expand Up @@ -69,22 +62,32 @@ function updateIconBasedOnProgress() {
console.log('attempting to update icon')
console.log('deepWorkTarget', deepWorkTarget, 'currentDeepWork', currentDeepWork)
let iconPath
let message

if (currentDeepWork >= deepWorkTarget) {
console.log('Greater than or equal to target. Setting to green icon')
message = `🎉 You've reached your target of ${deepWorkTarget} hours of deep work.`
iconPath = getIconPath('icon_green.png')
} else if (currentDeepWork > 0 && currentDeepWork < Math.floor(deepWorkTarget / 2)) {
console.log('Greater than 1 but less than 1/2 of target. Setting to yellow icon')
message = `🚧 You're halfway there. Keep up the good work.`
iconPath = getIconPath('icon_yellow.png')
} else if (currentDeepWork > 0 && currentDeepWork > Math.floor(deepWorkTarget / 2)) {
console.log('Half way there. Setting to blue icon')
message = `💡 You're close to the target. Keep it up.`
iconPath = getIconPath('icon_blue.png')
} else {
console.log('Still at 0')
message = ` 🏁 Let's get started on your deep work!`
iconPath = getIconPath('icon_red.png')
}

app.dock.setIcon(iconPath)
new Notification({
title: 'DeepFocus',
body: message,
icon: iconPath
}).show()
}
// Store user data in the electron-store and send to worker
function handleUserData(user: User): void {
Expand Down Expand Up @@ -144,39 +147,42 @@ function isBrowser(appName: string): appName is browser {
}

function startActivityMonitoring(mainWindow: Electron.BrowserWindow) {
monitoringInterval = setInterval(async () => {
const idleTime = powerMonitor.getSystemIdleTime()

// Skip if the system has been idle for more than 60 seconds
if (idleTime > 60) {
console.log(`System idle for ${idleTime} seconds.`)
return
}
if (!monitoringInterval) {
monitoringInterval = setInterval(async () => {
const idleTime = powerMonitor.getSystemIdleTime()

try {
const appName = await getActiveWindowApp() // Get the active application name
if (!appName) {
console.log('No active window app found')
// Skip if the system has been idle for more than 60 seconds
if (idleTime > 60) {
console.log(`System idle for ${idleTime} seconds.`)
return
}

console.log(`Active Application: ${appName}`)
let URL: string = ''
try {
const appName = await getActiveWindowApp() // Get the active application name
if (!appName) {
console.log('No active window app found')
return
}

if (isBrowser(appName)) {
URL = await getBrowserURL(appName)
}
console.log(`Active Application: ${appName}`)
let URL: string = ''

updateSiteTimeTracker(appName, currentSiteTimeTrackers, URL)
if (isBrowser(appName)) {
URL = getBaseURL(await getBrowserURL(appName))
}

// Send the active window info and URL to the renderer process
if (mainWindow) {
mainWindow.webContents.send('active-window-info', { appName, URL })
updateSiteTimeTracker(appName, currentSiteTimeTrackers, URL)

// Send the active window info and URL to the renderer process
if (mainWindow) {
mainWindow.webContents.send('active-window-info', { appName, URL })
}
} catch (error) {
console.error('Error getting active window or URL:', error)
}
} catch (error) {
console.error('Error getting active window or URL:', error)
}
}, 15000) // Run the monitoring function every 15 seconds
}, 15000) // Run the monitoring function every 15 seconds
console.log('Activity monitoring started.')
}
}

function stopActivityMonitoring() {
Expand Down Expand Up @@ -216,7 +222,7 @@ function calculateDeepWorkHours(
// Create the browser window
async function createWindow(): Promise<BrowserWindow> {
mainWindow = new BrowserWindow({
width: 900,
width: 600,
height: 670,
show: true,
autoHideMenuBar: false,
Expand Down Expand Up @@ -302,7 +308,6 @@ if (!app.requestSingleInstanceLock()) {
function handleUserLogout() {
console.log('Handling user logout')
store.delete('user')
resetCounters('daily', store, getSiteTrackers(), getDeepWorkHours())
stopActivityMonitoring()
}

Expand All @@ -312,6 +317,7 @@ function setupIPCListeners() {
console.log('event', event.ports)
const savedUser = store.get('user')
if (savedUser && mainWindow) {
console.log('setting up listeners & monitoring')
currentSiteTimeTrackers = getSiteTrackers()
startActivityMonitoring(mainWindow)
}
Expand Down
23 changes: 6 additions & 17 deletions src/main/productivityUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,9 @@ function getDomainFromUrl(url: string): string {
return parsedUrl.hostname || ''
}

export function getBaseURL(url: string): string | null {
try {
const urlObj = new URL(url)
return `${urlObj.protocol}//${urlObj.hostname}` // This gives you the base URL
} catch (error) {
console.error('Invalid URL:', error)
return null
}
export function getBaseURL(url: string): string {
const urlObj = new URL(url)
return `${urlObj.protocol}//${urlObj.hostname}` // This gives you the base URL
}

function isProductiveUrl(url: string): boolean {
Expand Down Expand Up @@ -103,23 +98,17 @@ export function formatTime(milliseconds: number): string {
export function updateSiteTimeTracker(
appName: string,
timeTrackers: SiteTimeTracker[],
parsedURL?: string
url?: string
): SiteTimeTracker {
const currentTime = Number((Date.now() / 1000).toString().slice(0, -3))

// Check if the windowInfo has a valid URL, and if so, extract the base URL
let url
if (parsedURL) {
console.log('testing sanity, ', parsedURL)
url = parsedURL
}
let trackerKey = ''
let trackerTitle = ''

if (url && isValidURL(url)) {
// For URLs, use the base URL as the tracker key and the title as the URL's base domain
trackerKey = getBaseURL(url) as string
trackerTitle = getBaseURL(url) as string
trackerKey = url
trackerTitle = url
} else {
// If it's a desktop app (no valid URL), use the app path and name for the tracker
trackerKey = appName || 'Unknown App'
Expand Down
24 changes: 17 additions & 7 deletions src/renderer/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { lazy, Suspense, onMount, createSignal, ComponentProps } from 'solid-js'
import { Router, Route, A, useLocation } from '@solidjs/router'
import { lazy, Suspense, onMount, createSignal, ComponentProps, createEffect } from 'solid-js'
import { Router, Route, A, useLocation, useNavigate } from '@solidjs/router'
import { render } from 'solid-js/web'
import { AuthProvider, useAuth } from './lib/AuthContext'

Expand All @@ -8,11 +8,11 @@ import './assets/main.css'
import logo from './assets/deepWork.svg'
import { IoSettingsSharp, SiSimpleanalytics, VsHome, IoLogOutOutline } from './components/ui/icons'
import { Button } from './components/ui/button'
import Home from './Home'

// Lazy load the components
const Login = lazy(() => import('./Login'))
const Signup = lazy(() => import('./Signup'))
const Home = lazy(() => import('./Home'))
const BarChart = lazy(() => import('./BarChart'))

const Onboarding = lazy(() => import('./Onboarding'))
Expand All @@ -23,6 +23,7 @@ const App = (props: ComponentProps<typeof Router>) => {
const [isLoggedIn, setIsLoggedIn] = useAuth()
const [isNewUser, setIsNewUser] = createSignal(true)
const location = useLocation()
const navigate = useNavigate()

onMount(() => {
const token = localStorage.getItem('token') as string
Expand All @@ -39,11 +40,16 @@ const App = (props: ComponentProps<typeof Router>) => {
setIsLoggedIn(false)
setIsNewUser(false)
stopActivityMonitoring()
navigate('/')
}

createEffect(() => {
console.log('Updated loggedIn:', isLoggedIn())
})

const NavBar = () => (
<>
<header class="flex justify-between items-center p-4 bg-gray-800 w-full">
<header class="flex justify-between items-center p-4 bg-gray-800 opacity-[0.50] w-full">
<img alt="logo" class="logo" src={logo} />
<nav class="flex items-center justify-center space-x-4">
{!isLoggedIn() ? (
Expand All @@ -58,11 +64,15 @@ const App = (props: ComponentProps<typeof Router>) => {
<Button>Login</Button>
</A>
)
) : (
// Show Login by default for returning users
) : location.pathname === '/' ? (
<A href="/login" class="px-4 py-2 rounded text-white">
<Button>Login</Button>
</A>
) : (
// Show Login by default for returning users
<A href="/signup" class="px-4 py-2 rounded text-white">
<Button>Sign Up</Button>
</A>
)}
</>
) : (
Expand All @@ -76,7 +86,7 @@ const App = (props: ComponentProps<typeof Router>) => {
<A href="/settings" class="px-4 py-2 rounded text-white flex items-center">
<IoSettingsSharp />
</A>
<Button onClick={handleLogout} class="px-4 py-2 rounded text-white">
<Button onClick={handleLogout} class="px-4 rounded text-white">
<IoLogOutOutline />
</Button>
</>
Expand Down
5 changes: 3 additions & 2 deletions src/renderer/src/BarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from 'chart.js'
import { Bar } from 'solid-chartjs'
import { Button } from './components/ui/button'
import { VsRefresh } from './components/ui/icons'

const BarChart = () => {
const [chartData, setChartData] = createSignal({
Expand Down Expand Up @@ -84,8 +85,8 @@ const BarChart = () => {

return (
<div>
<Button class="mb-4 p-2 bg-blue-500 text-white" onClick={fetchDeepWorkData}>
Refresh Data
<Button class="mt-2 px-4 rounded text-white" onClick={fetchDeepWorkData}>
<VsRefresh />
</Button>
<Bar data={chartData()} options={chartOptions} width={500} height={500} />
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/renderer/src/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const Home = () => {
createEffect(() => {
console.log('Updated progress:', progress())
console.log('Updated windowInfo:', activeWindowInfo())
console.log('Updated loggedIn:', loggedIn())
})

const handleActiveWindowInfo = (event, windowInfo) => {
Expand Down Expand Up @@ -90,6 +91,7 @@ const Home = () => {
{!loggedIn() || !user ? (
<div>
<h1 class="mb-10 text-2xl font-light">Welcome to Deep Focus</h1>
<SandTimer />
</div>
) : (
<div class="space-y-8">
Expand All @@ -115,7 +117,6 @@ const Home = () => {
)}
</div>
)}
{!loggedIn() && <SandTimer />}
</div>
)
}
Expand Down
Loading

0 comments on commit 844885f

Please sign in to comment.