Skip to content

Commit

Permalink
Merge pull request #70 from nomandhoni-cs/master
Browse files Browse the repository at this point in the history
Releasing Blink Eye `v1.7.0` with auto run on startup and sound on reminder
  • Loading branch information
nomandhoni-cs authored Nov 8, 2024
2 parents 38dd299 + 32a6cd1 commit 097cbca
Show file tree
Hide file tree
Showing 16 changed files with 507 additions and 338 deletions.
Binary file modified bun.lockb
Binary file not shown.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "blink-eye",
"private": true,
"version": "1.6.0",
"version": "1.7.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand All @@ -17,7 +17,9 @@
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slider": "^1.2.1",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-switch": "^1.1.1",
"@radix-ui/react-tabs": "^1.1.1",
"@radix-ui/react-tooltip": "^1.1.3",
"@tauri-apps/api": "2.0.3",
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "Blink-Eye"
version = "1.6.0"
version = "1.7.0"
description = "A minimalist eye care reminder app."
authors = ["Noman Dhoni"]
edition = "2021"
Expand Down
Binary file modified src-tauri/assets/done.mp3
Binary file not shown.
6 changes: 5 additions & 1 deletion src-tauri/capabilities/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
"core:app:allow-default-window-icon",
"process:default",
"process:allow-exit",
"updater:default"
"updater:default",
"core:path:allow-join",
"core:path:allow-dirname",
"core:path:allow-resolve",
"core:path:allow-resolve-directory"
]
}
10 changes: 6 additions & 4 deletions src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2.0.6",
"productName": "Blink Eye",
"version": "1.6.0",
"version": "1.7.0",
"identifier": "com.blinkeye.app",
"build": {
"beforeDevCommand": "bun run dev",
Expand All @@ -23,11 +23,11 @@
}
],
"security": {
"csp": "default-src 'self'; media-src 'self' asset: https://asset.localhost;",
"csp": "null",
"assetProtocol": {
"enable": true,
"scope": [
"**"
"$RESOURCE/*"
]
}
}
Expand All @@ -44,7 +44,9 @@
"icons/icon.ico",
"icons/icon.png"
],
"resources": ["assets/done.mp3"],
"resources": {
"assets/done.mp3": "done.mp3"
},
"externalBin": [],
"copyright": "Noman Dhoni",
"category": "Productivity",
Expand Down
77 changes: 55 additions & 22 deletions src/components/AutoStartToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,60 @@
// AutoStartToggle.tsx
import { useState, useEffect } from "react";
import { enable, isEnabled, disable } from "@tauri-apps/plugin-autostart";
import { Checkbox } from "./ui/checkbox";
import { Label } from "./ui/label";
import { Switch } from "./ui/switch";
import toast from "react-hot-toast";
import { load } from "@tauri-apps/plugin-store";

const AutoStartToggle = () => {
const [isAutoStartEnabled, setIsAutoStartEnabled] = useState(false);

useEffect(() => {
const checkAutoStartStatus = async () => {
const initializeAutoStart = async () => {
try {
const status = await isEnabled();
setIsAutoStartEnabled(status);
// Load initial configuration store
const store = await load("initialSetupConfig.json", {
autoSave: false,
});
const runOnStartUp = await store.get<boolean>(
"isRunOnStartUpEnabledByDefault"
);

// If setting does not exist in store, enable autostart by default
if (runOnStartUp === null || runOnStartUp === undefined || false) {
await enable();
await store.set("isRunOnStartUpEnabledByDefault", true);
toast.success("AutoStart Enabled by Default", {
duration: 2000,
position: "bottom-right",
});
setIsAutoStartEnabled(true);
} else {
// Otherwise, check actual autostart status
const status = await isEnabled();
setIsAutoStartEnabled(status);
}
} catch (error) {
console.error("Failed to get autostart status:", error);
console.error("Failed to initialize autostart:", error);
}
};
checkAutoStartStatus();
initializeAutoStart();
}, []);

const handleCheckboxChange = async (checked: boolean) => {
try {
if (checked) {
await enable();
toast.success("Enabled Autostart", {
duration: 2000,
position: "bottom-right",
});
} else {
await disable();
toast.success("Disabled Autostart", {
duration: 2000,
position: "bottom-right",
});
}
setIsAutoStartEnabled(checked);
} catch (error) {
Expand All @@ -32,22 +63,24 @@ const AutoStartToggle = () => {
};

return (
<div className="items-top flex space-x-2">
<Checkbox
id="autostart"
checked={isAutoStartEnabled}
onCheckedChange={handleCheckboxChange}
/>
<div className="grid gap-1.5 leading-none">
<label
htmlFor="autostart"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Run Blink Eye on startup.
</label>
<p className="text-sm text-muted-foreground">
Turn this on for best usage.
</p>
<div className="">
<div className="flex flex-row items-center justify-between rounded-lg border p-4">
<div className="space-y-0.5">
<Label
htmlFor="autostart"
className="font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Run on Startup
</Label>
<p className="text-sm text-muted-foreground">
Automatically start this app when your computer boots up
</p>
</div>
<Switch
id="autostart"
checked={isAutoStartEnabled}
onCheckedChange={handleCheckboxChange}
/>
</div>
</div>
);
Expand Down
130 changes: 130 additions & 0 deletions src/components/backgrounds/StarryBackground.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import React, { useEffect, useRef } from "react";

const StarryBackground: React.FC = () => {
const canvasRef = useRef<HTMLCanvasElement | null>(null);

useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;

const c = canvas.getContext("2d");
if (!c) return;

const n_stars = 150;
const colors = [
"#ffffff",
"#ffd700",
"#00d4b4",
"#a1c4fd",
"#ff74d0",
...Array(98).fill("#fff"),
]; // Stars visible in light and dark

const randomInt = (max: number, min: number) =>
Math.floor(Math.random() * (max - min) + min);

class Star {
x: number;
y: number;
radius: number;
color: string;
dy: number;

constructor(
x: number = randomInt(0, canvas?.width ?? window.innerWidth),
y: number = randomInt(0, canvas?.height ?? window.innerHeight),
radius: number = Math.random() * 1.1,
color: string = colors[randomInt(0, colors.length)]
) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.dy = -Math.random() * 0.3;
}

draw() {
// Assert that 'c' is not null
const context = c as CanvasRenderingContext2D;
context.beginPath();
context.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
context.shadowBlur = randomInt(3, 15);
context.shadowColor = this.color;
context.strokeStyle = this.color;
context.fillStyle = "rgba(255, 255, 255, .5)";
context.fill();
context.stroke();
context.closePath();
}

update(arrayStars: Star[]) {
if (this.y - this.radius < 0) this.createNewStar(arrayStars);
this.y += this.dy;
this.draw();
}

createNewStar(arrayStars: Star[]) {
const i = arrayStars.indexOf(this);
arrayStars.splice(i, 1);
arrayStars.push(new Star());
}
}

let stars: Star[] = [];
const init = () => {
for (let i = 0; i < n_stars; i++) {
stars.push(new Star());
}
};
init();

const animate = () => {
requestAnimationFrame(animate);
c.clearRect(0, 0, canvas.width, canvas.height);
stars.forEach((s) => s.update(stars));
};

animate();

const handleResize = () => {
if (!canvas) return;
const width = window.innerWidth;
const height = window.innerHeight;
const dpr = window.devicePixelRatio || 1;

// Set canvas size with device pixel ratio to avoid blurriness
canvas.width = width * dpr;
canvas.height = height * dpr;
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;

// Scale the context for retina displays
c.scale(dpr, dpr);

stars = [];
init();
};

window.addEventListener("resize", handleResize);

// Initial resize call
handleResize();

return () => {
window.removeEventListener("resize", handleResize);
};
}, []);

return (
<canvas
ref={canvasRef}
className="w-full h-full fixed inset-0 -z-10 overflow-hidden"
style={{
background:
"linear-gradient(to bottom, rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.6))",
}}
/>
);
};

export default StarryBackground;
26 changes: 26 additions & 0 deletions src/components/ui/slider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from "react";
import * as SliderPrimitive from "@radix-ui/react-slider";

import { cn } from "../../lib/utils";

const Slider = React.forwardRef<
React.ElementRef<typeof SliderPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
>(({ className, ...props }, ref) => (
<SliderPrimitive.Root
ref={ref}
className={cn(
"relative flex w-full touch-none select-none items-center",
className
)}
{...props}
>
<SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-secondary">
<SliderPrimitive.Range className="absolute h-full bg-primary" />
</SliderPrimitive.Track>
<SliderPrimitive.Thumb className="block h-5 w-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" />
</SliderPrimitive.Root>
));
Slider.displayName = SliderPrimitive.Root.displayName;

export { Slider };
27 changes: 27 additions & 0 deletions src/components/ui/switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as React from "react";
import * as SwitchPrimitives from "@radix-ui/react-switch";

import { cn } from "../../lib/utils";

const Switch = React.forwardRef<
React.ElementRef<typeof SwitchPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
>(({ className, ...props }, ref) => (
<SwitchPrimitives.Root
className={cn(
"peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
className
)}
{...props}
ref={ref}
>
<SwitchPrimitives.Thumb
className={cn(
"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
)}
/>
</SwitchPrimitives.Root>
));
Switch.displayName = SwitchPrimitives.Root.displayName;

export { Switch };
Loading

0 comments on commit 097cbca

Please sign in to comment.