Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e1675a2
saving current changes so that the theme page opens first
harryalloyd Dec 10, 2025
8350f5b
added feature so that the user can select a font
harryalloyd Dec 10, 2025
f25e845
Added all the theme options under the theme tab in the settings
harryalloyd Dec 10, 2025
468fea2
fixed some bugs and made is so that whats chosen on the theme pages a…
harryalloyd Dec 10, 2025
ce73397
fixed bug with light mode/dark mode not being checked
harryalloyd Dec 10, 2025
647656b
Got rid of the background color idea
harryalloyd Dec 10, 2025
5595fe3
now the light mode/dark mode bug is actually gone
harryalloyd Dec 10, 2025
fcb1184
Made it so that the blur effect works on the opening page as well as …
harryalloyd Dec 11, 2025
ed1d1a7
Selecting the font style now changes all other text to that font
harryalloyd Dec 11, 2025
c04632d
slightly changed up the UI for the font and blur theme
harryalloyd Dec 11, 2025
dcc9a14
Made it so that the to-do-list is now dark grey or white depending on…
harryalloyd Dec 11, 2025
80d431f
Light mode and dark mode now affect all widgets
harryalloyd Dec 11, 2025
4e7ab4c
Updated the light mode slightly so that the blur looks better on the …
harryalloyd Dec 11, 2025
0f7a67d
Fixed bug on opening theme page and made slight UI changes. Also, fix…
harryalloyd Dec 12, 2025
a1fad20
Merge branch 'main' into theme-selection-page
harryalloyd Dec 12, 2025
7ef4f11
Fixed issues with opening theme page appearing on every reload, the f…
harryalloyd Dec 13, 2025
99d0968
Removed the selected button on the blur theme, it was a little unnece…
harryalloyd Dec 13, 2025
25f8d6e
Restore Templates menu
bacurrah Dec 15, 2025
246005e
Use background image
bacurrah Dec 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 24 additions & 11 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ body {
height: 100svh;
margin: 0;
color: #fff;
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-family: var(--app-font);
background-image: url(https://images.unsplash.com/photo-1507166763745-bfe008fbb831?q=80&w=960&auto=format);
background-size: cover;
overflow: hidden;
Expand All @@ -36,15 +36,9 @@ body {
z-index: -1;
}

.content h1 {
font-size: 3.6rem;
font-weight: 700;
}

.content p {
font-size: 1.5rem;
font-weight: 400;
opacity: 0.5;
:root {
--blur-amount: 40px;
--app-font: Arial, sans-serif;
}

.container {
Expand All @@ -54,11 +48,30 @@ body {
border-radius: 8px;
border: 1px solid #fff2;

backdrop-filter: blur(40px);
backdrop-filter: blur(var(--blur-amount));
transform: translateZ(0);
backface-visibility: hidden;
}

/* Light mode styling */
.lightMode .container {
background-color: rgba(255, 255, 255, 0.95);
border: 1px solid rgba(0, 0, 0, 0.1);
}

.lightMode {
color: #000;
}

.lightMode .button {
color: rgba(0, 0, 0, 0.8);
}

.lightMode .button:hover {
border-color: rgba(0, 0, 0, 0.3);
color: #000;
}

.container::before {
content: "";
position: absolute;
Expand Down
111 changes: 90 additions & 21 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Grid } from "./Grid";
import { nanoid } from "nanoid";
import { toPng } from "html-to-image";
import styles from "./App.css";
import OpeningTheme from "./themeOpenPage";

export interface Template {
name: string;
Expand All @@ -25,13 +26,15 @@ interface AppContextType {
deleting: boolean;
hidden: boolean;
menuOpen: boolean;
theme: 'light' | 'dark';

setWidgets: React.Dispatch<React.SetStateAction<WidgetState<any>[]>>;
setTemplates: React.Dispatch<React.SetStateAction<Template[]>>;
setEditing: React.Dispatch<React.SetStateAction<boolean>>;
setDeleting: React.Dispatch<React.SetStateAction<boolean>>;
setHidden: React.Dispatch<React.SetStateAction<boolean>>;
setMenuOpen: React.Dispatch<React.SetStateAction<boolean>>;
setTheme: React.Dispatch<React.SetStateAction<'light' | 'dark'>>;

saveTemplate: (name?: string) => void;
loadTemplate: (index?: number) => void;
Expand Down Expand Up @@ -67,34 +70,61 @@ const App = () => {
let [widgets, setWidgets] = useState<WidgetState<any>[]>([]);
let [templates, setTemplates] = useState<Template[]>([]);
let [activeTemplate, setActiveTemplate] = useState(0);
const [openingTheme, setOpeningTheme] = useState(() => {
const completed = localStorage.getItem("theme_setup_completed");
return completed !== "true";
});
const [theme, setTheme] = useState<'light' | 'dark'>('dark');

const gridRef = useRef(null);

async function saveTemplate(name?: string) {
const template = {
name: name ?? templates[activeTemplate]?.name ?? "Default",
image: await toPng(gridRef.current, {
canvasWidth: 240,
canvasHeight: 135,
}),
widgets: structuredClone(widgets),
pinned: false,
};
try {
const templateWithoutImage = {
name: name ?? templates[activeTemplate]?.name ?? "Default",
image: null,
widgets: structuredClone(widgets),
pinned: false,
};

if (name === null || name === undefined) {
const _templates = [...templates];
_templates[activeTemplate] = template;
let _templates: Template[];
let _activeTemplate: number;

templates = [..._templates];
setTemplates(templates);
} else {
templates = [...templates, template];
activeTemplate = templates.length;
if (name === null || name === undefined) {
_templates = [...templates];
_templates[activeTemplate] = templateWithoutImage;
_activeTemplate = activeTemplate;
} else {
_templates = [...templates, templateWithoutImage];
_activeTemplate = templates.length;
}

localStorage.setItem("templates", JSON.stringify(_templates));
localStorage.setItem("activeTemplate", JSON.stringify(_activeTemplate));

templates = _templates;
activeTemplate = _activeTemplate;
setTemplates(templates);
setActiveTemplate(activeTemplate);
}
if (name !== null && name !== undefined) {
setActiveTemplate(activeTemplate);
}

try {
const image = await toPng(gridRef.current, {
canvasWidth: 240,
canvasHeight: 135,
});

writeTemplates();
_templates[_activeTemplate].image = image;
templates = _templates;
localStorage.setItem("templates", JSON.stringify(templates));
setTemplates([...templates]);
} catch (screenshotError) {
console.warn("Screenshot failed, but template was saved:", screenshotError);
}
} catch (error) {
console.error("Error in saveTemplate:", error);
}
}

function loadTemplate(index?: number) {
Expand Down Expand Up @@ -161,11 +191,47 @@ const App = () => {

useEffect(() => {
readTemplates();

const blurAmount = localStorage.getItem("theme_blurAmount");
if (blurAmount !== null) {
document.documentElement.style.setProperty('--blur-amount', `${blurAmount}px`);
}

const selectedFont = localStorage.getItem("theme_font");
if (selectedFont && selectedFont !== "") {
document.documentElement.style.setProperty('--app-font', selectedFont);
}

const lightMode = localStorage.getItem("theme_lightMode");
if (lightMode === "true") {
setTheme('light');
} else {
setTheme('dark');
}
}, []);

if (openingTheme) {
return <OpeningTheme onContinue={() => {
setOpeningTheme(false);
localStorage.setItem("theme_setup_completed", "true");

const blurAmount = localStorage.getItem("theme_blurAmount");
if (blurAmount !== null) {
document.documentElement.style.setProperty('--blur-amount', `${blurAmount}px`);
}

const lightMode = localStorage.getItem("theme_lightMode");
if (lightMode === "true") {
setTheme('light');
} else {
setTheme('dark');
}
}} />;
}

return (
<div
className={styles.content}
className={`${styles.content} ${theme === 'light' ? 'lightMode' : ''}`}
onClick={(e) => {
if (e.target === e.currentTarget) {
setMenuOpen(false);
Expand All @@ -182,13 +248,15 @@ const App = () => {
deleting,
hidden,
menuOpen,
theme,

setWidgets,
setTemplates,
setEditing,
setDeleting,
setHidden,
setMenuOpen,
setTheme,

saveTemplate,
loadTemplate,
Expand All @@ -201,6 +269,7 @@ const App = () => {
<Grid width={24} height={12} ref={gridRef}>
{widgets.map((state) => {
const map = WidgetMap[state.type];
if (!map) return null;
const Component = map.component;
return (
<Widget
Expand Down
14 changes: 14 additions & 0 deletions src/Menu.css
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,20 @@
text-align: center;
}

.item-input select {
color: #fff;
background-color: #fff2;
border: 1px solid #fff2;
border-radius: 4px;
outline: none;
cursor: pointer;
}

.item-input select option {
background-color: rgba(60, 60, 60, 0.95);
color: #fff;
}

.widget-list {
display: flex;
flex-flow: row wrap;
Expand Down
Loading