-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #87 from nomandhoni-cs/develop
Added Workday setup for v1.9.0 and update toast
- Loading branch information
Showing
30 changed files
with
1,263 additions
and
240 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { useEffect } from "react"; | ||
import { BaseDirectory } from "@tauri-apps/api/path"; | ||
import { exists } from "@tauri-apps/plugin-fs"; | ||
import Database from "@tauri-apps/plugin-sql"; | ||
import { load } from "@tauri-apps/plugin-store"; | ||
|
||
const ConfigDataLoader: React.FC = () => { | ||
const defaultWorkday = { | ||
Monday: { start: "09:00", end: "17:00" }, | ||
Tuesday: { start: "09:00", end: "17:00" }, | ||
Wednesday: { start: "09:00", end: "17:00" }, | ||
Thursday: { start: "09:00", end: "17:00" }, | ||
Friday: { start: "09:00", end: "17:00" }, | ||
Saturday: null, | ||
Sunday: null, | ||
}; | ||
|
||
useEffect(() => { | ||
const setupDatabase = async () => { | ||
// Check if the database file exists | ||
const dbExists = await exists("appconfig.db", { | ||
baseDir: BaseDirectory.AppData, | ||
}); | ||
|
||
// Initialize the database | ||
|
||
if (!dbExists) { | ||
const db = await Database.load("sqlite:appconfig.db"); | ||
console.log("Database does not exist. Initializing..."); | ||
|
||
// Create the tables | ||
await db.execute(` | ||
CREATE TABLE IF NOT EXISTS config ( | ||
key TEXT PRIMARY KEY, | ||
value TEXT | ||
); | ||
`); | ||
|
||
// Insert default values | ||
await db.execute(`INSERT INTO config (key, value) VALUES (?, ?);`, [ | ||
"blinkEyeWorkday", | ||
JSON.stringify(defaultWorkday), | ||
]); | ||
await db.execute(`INSERT INTO config (key, value) VALUES (?, ?);`, [ | ||
"isWorkdayEnabled", | ||
"false", | ||
]); | ||
await db.execute(`INSERT INTO config (key, value) VALUES (?, ?);`, [ | ||
"isUpdateAvailable", | ||
"false", | ||
]); | ||
await db.execute(`INSERT INTO config (key, value) VALUES (?, ?);`, [ | ||
"usingStrictMode", | ||
"false", | ||
]); | ||
console.log("Database initialized with default configuration."); | ||
} else { | ||
console.log("Database already exists. No action needed."); | ||
} | ||
|
||
const storeExists = await exists("store.json", { | ||
baseDir: BaseDirectory.AppData, | ||
}); | ||
if (!storeExists) { | ||
const store = await load("store.json", { autoSave: false }); | ||
await store.set("blinkEyeReminderDuration", 20); | ||
await store.set("blinkEyeReminderInterval", 20); | ||
await store.set( | ||
"blinkEyeReminderScreenText", | ||
"Look 20 feet away to protect your eyes." | ||
); | ||
await store.save(); | ||
} else { | ||
console.log("Store already exists. No action needed."); | ||
} | ||
}; | ||
|
||
setupDatabase(); | ||
}, []); | ||
|
||
return null; // This component does not render anything | ||
}; | ||
|
||
export default ConfigDataLoader; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import { useEffect, useState } from "react"; | ||
import { WebviewWindow } from "@tauri-apps/api/webviewWindow"; | ||
import Database from "@tauri-apps/plugin-sql"; | ||
import { usePremiumFeatures } from "../contexts/PremiumFeaturesContext"; | ||
import { load } from "@tauri-apps/plugin-store"; | ||
import { useTrigger } from "../contexts/TriggerReRender"; | ||
|
||
// Define the type for workday configuration | ||
type Workday = { [day: string]: { start: string; end: string } } | null; | ||
|
||
const ReminderHandler = () => { | ||
const { trigger } = useTrigger(); // Use the trigger value from the context | ||
const [interval, setInterval] = useState<number>(20); | ||
const [workday, setWorkday] = useState<Workday>(null); | ||
const [isWorkdayEnabled, setIsWorkdayEnabled] = useState<boolean>(false); | ||
const { canAccessPremiumFeatures } = usePremiumFeatures(); | ||
|
||
// Function to open the reminder window | ||
const openReminderWindow = () => { | ||
console.log("Opening reminder window..."); | ||
const webview = new WebviewWindow("ReminderWindow", { | ||
url: "/reminder", | ||
fullscreen: true, | ||
alwaysOnTop: true, | ||
title: "Take A Break Reminder - Blink Eye", | ||
skipTaskbar: true, | ||
}); | ||
|
||
webview.once("tauri://created", () => { | ||
console.log("Reminder window created"); | ||
}); | ||
|
||
webview.once("tauri://error", (e) => { | ||
console.error("Error creating reminder window:", e); | ||
}); | ||
}; | ||
|
||
// Fetch settings when `trigger` changes | ||
useEffect(() => { | ||
const fetchSettings = async () => { | ||
console.log("Fetching settings due to trigger:", trigger); | ||
const db = await Database.load("sqlite:appconfig.db"); | ||
const store = await load("store.json", { autoSave: false }); | ||
|
||
// Load the reminder interval from storage | ||
const storedInterval = await store.get<number>( | ||
"blinkEyeReminderInterval" | ||
); | ||
if (storedInterval) setInterval(storedInterval); | ||
|
||
// Fetch workday setup from the database | ||
type ConfigResult = { value: string }; | ||
const workdayData = (await db.select( | ||
"SELECT value FROM config WHERE key = ?", | ||
["blinkEyeWorkday"] | ||
)) as ConfigResult[]; | ||
if (workdayData.length > 0 && workdayData[0].value) { | ||
try { | ||
const parsedWorkday = JSON.parse(workdayData[0].value) as Workday; | ||
setWorkday(parsedWorkday); | ||
} catch (error) { | ||
console.error("Failed to parse workday data:", error); | ||
} | ||
} | ||
|
||
// Fetch whether workday is enabled | ||
const isEnabledData = (await db.select( | ||
"SELECT value FROM config WHERE key = ?", | ||
["isWorkdayEnabled"] | ||
)) as ConfigResult[]; | ||
|
||
if (isEnabledData.length > 0 && isEnabledData[0].value) { | ||
setIsWorkdayEnabled(isEnabledData[0].value === "true"); | ||
} | ||
console.log(workdayData, "workdayData"); | ||
console.log(storedInterval, "storedInterval"); | ||
console.log(isWorkdayEnabled, "isWorkdayEnabled"); | ||
}; | ||
|
||
fetchSettings(); | ||
}, [trigger]); // Refetch settings when the trigger updates | ||
|
||
// Handle interval-based reminder logic | ||
useEffect(() => { | ||
console.log("Initializing reminder logic"); | ||
let timer: number | null = null; | ||
|
||
const startReminder = () => { | ||
console.log("Starting reminder timer with interval:", interval); | ||
timer = window.setInterval(() => { | ||
openReminderWindow(); | ||
}, interval * 60 * 1000); // The interval value will be non-null | ||
}; | ||
|
||
const checkWorkdayAndStartTimer = () => { | ||
const now = new Date(); | ||
const day = now.toLocaleString("en-US", { weekday: "long" }); | ||
const todayWorkday = workday?.[day]; | ||
|
||
if (canAccessPremiumFeatures && isWorkdayEnabled) { | ||
if (todayWorkday) { | ||
const [startHour, startMinute] = todayWorkday.start | ||
.split(":") | ||
.map(Number); | ||
const [endHour, endMinute] = todayWorkday.end.split(":").map(Number); | ||
|
||
const startTime = new Date(); | ||
startTime.setHours(startHour, startMinute, 0, 0); | ||
|
||
const endTime = new Date(); | ||
endTime.setHours(endHour, endMinute, 0, 0); | ||
|
||
console.log("Start time:", startTime); | ||
console.log("End time:", endTime); | ||
console.log("Now:", now); | ||
|
||
if (now >= startTime && now <= endTime) { | ||
console.log("Within workday window. Starting reminder."); | ||
startReminder(); | ||
} else { | ||
console.log("Outside workday window. Reminder not started."); | ||
} | ||
} else { | ||
console.log("No workday setup for today. Reminder skipped."); | ||
} | ||
} else { | ||
console.log("Non-premium user or workday disabled. Starting reminder."); | ||
startReminder(); | ||
} | ||
}; | ||
|
||
// Start reminder logic if necessary | ||
if (workday || !canAccessPremiumFeatures) { | ||
checkWorkdayAndStartTimer(); | ||
} | ||
|
||
return () => { | ||
if (timer !== null) window.clearInterval(timer); // Cleanup previous timers | ||
}; | ||
}, [workday, isWorkdayEnabled, canAccessPremiumFeatures, interval]); | ||
|
||
return null; | ||
}; | ||
|
||
export default ReminderHandler; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { useState, useEffect } from "react"; | ||
import { Label } from "./ui/label"; | ||
import { Switch } from "./ui/switch"; | ||
import Database from "@tauri-apps/plugin-sql"; | ||
|
||
interface ConfigRow { | ||
value: string; | ||
} | ||
|
||
const StrictModeToggle = () => { | ||
const [isStrictModeEnabled, setIsStrictModeEnabled] = useState(false); | ||
|
||
useEffect(() => { | ||
const initializeStrictMode = async () => { | ||
try { | ||
// Load initial configuration store | ||
const db = await Database.load("sqlite:appconfig.db"); | ||
|
||
// Retrieve the 'usingStrictMode' value from the config table | ||
const result: ConfigRow[] = await db.select( | ||
"SELECT value FROM config WHERE key = 'usingStrictMode';" | ||
); | ||
|
||
if (result.length > 0) { | ||
setIsStrictModeEnabled(result[0].value === "true"); | ||
} | ||
} catch (error) { | ||
console.error("Failed to initialize strict mode:", error); | ||
} | ||
}; | ||
initializeStrictMode(); | ||
}, []); | ||
|
||
const handleCheckboxChange = async (checked: boolean) => { | ||
try { | ||
const db = await Database.load("sqlite:appconfig.db"); | ||
|
||
// Use an `INSERT OR REPLACE` or `UPDATE` query | ||
await db.execute( | ||
` | ||
INSERT INTO config (key, value) VALUES ('usingStrictMode', ?) | ||
ON CONFLICT(key) DO UPDATE SET value = excluded.value; | ||
`, | ||
[checked ? "true" : "false"] | ||
); | ||
|
||
setIsStrictModeEnabled(checked); | ||
} catch (error) { | ||
console.error("Failed to update strict mode status:", error); | ||
} | ||
}; | ||
|
||
return ( | ||
<div className="flex flex-row items-center justify-between rounded-lg border p-4"> | ||
<div className="space-y-0.5"> | ||
<Label | ||
htmlFor="strictmode" | ||
className="font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" | ||
> | ||
Use Strict Mode | ||
</Label> | ||
<p className="text-sm text-muted-foreground"> | ||
This will hide the 'Skip this time' button to force follow the break. | ||
</p> | ||
</div> | ||
<Switch | ||
id="strictmode" | ||
checked={isStrictModeEnabled} | ||
onCheckedChange={handleCheckboxChange} | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export default StrictModeToggle; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.