-
I'm currently working on new fascinating projects, so be sure to follow me!
-
-
Student / Software Developer
+
+
+ I'm currently working on new fascinating projects, so be sure to
+ follow me!
+
-
- I am currently pursuing a degree in Computer Science at the Silesian University of Technology in Gliwice. Programming is my passion. I have experience working with a variety of languages. Recently, I have been focusing my attention on Rust and JavaScript.
-
-
- I am also interested in artificial intelligence and machine learning. In addition, I actively create and develop many projects to further enhance my skills.
-
+
Student / Software Developer
-
My Projects
-
-
Go to Projects
+
+ I am currently pursuing a degree in Computer Science at the Silesian
+ University of Technology in Gliwice. Programming is my passion. I have
+ experience working with a variety of languages. Recently, I have been
+ focusing my attention on Rust and JavaScript.
+
+
+ I am also interested in artificial intelligence and machine learning.
+ In addition, I actively create and develop many projects to further
+ enhance my skills.
+
-
+
My Projects
-
Mike around the web
-
+
Go to Projects
+
+
Mike around the web
+
+
+
+
+
+
+
+

+
+ 🌙
+ Dark Mode
+
+
+
-
-
-
-
-

-
- 🌙
- Dark Mode
-
-
-
-
-
-
-
+
diff --git a/main.js b/main.js
index 4bcb1ba..830750b 100644
--- a/main.js
+++ b/main.js
@@ -2,51 +2,38 @@ const root = document.documentElement;
const themeText = document.querySelector(".theme-text");
const themeIcon = document.querySelector(".material-icons");
-const isDarkMode = () => root.classList.contains("dark");
-
-const setDarkMode = () => {
- root.classList.add("dark");
- themeText.textContent = "Dark Mode";
- themeIcon.innerHTML = "🌙";
+const THEMES = {
+ light: { class: "", text: "Light Mode", icon: "☀️" },
+ dark: { class: "dark", text: "Dark Mode", icon: "🌙" },
};
-const setLightMode = () => {
- root.classList.remove("dark");
- themeText.textContent = "Light Mode";
- themeIcon.innerHTML = "☀️";
-};
+function updateTheme(mode) {
+ root.classList.toggle("dark", mode === "dark");
+ themeText.textContent = THEMES[mode].text;
+ themeIcon.textContent = THEMES[mode].icon;
+ localStorage.setItem("preferredTheme", mode);
+}
-const toggleTheme = () => {
- if (isDarkMode()) {
- setLightMode();
- localStorage.setItem("preferredTheme", "light");
- } else {
- setDarkMode();
- localStorage.setItem("preferredTheme", "dark");
+function getPreferredTheme() {
+ const stored = localStorage.getItem("preferredTheme");
+ if (stored === "dark" || stored === "light") {
+ return stored;
}
-};
-const checkPreferredTheme = () => {
- const preferredTheme = localStorage.getItem("preferredTheme");
- if (preferredTheme === "dark") {
- setDarkMode();
- } else if (preferredTheme === "light") {
- setLightMode();
- } else {
- const prefersDarkScheme = window.matchMedia(
- "(prefers-color-scheme: dark)"
- ).matches;
- if (prefersDarkScheme) {
- setDarkMode();
- } else {
- setLightMode();
- }
- }
-};
+ return window.matchMedia("(prefers-color-scheme: dark)").matches
+ ? "dark"
+ : "light";
+}
-document.querySelector("#year").innerHTML = new Date().getFullYear();
+if ("serviceWorker" in navigator) {
+ window.addEventListener("load", () => {
+ navigator.serviceWorker.register("/sw.js");
+ });
+}
-checkPreferredTheme();
+navigator.serviceWorker.addEventListener("controllerchange", () => {
+ console.log("New version available, reloading...");
+ window.location.reload();
+});
-const themeButton = document.querySelector(".theme");
-themeButton.addEventListener("click", toggleTheme);
+updateTheme(getPreferredTheme());
diff --git a/sw.js b/sw.js
new file mode 100644
index 0000000..e82f476
--- /dev/null
+++ b/sw.js
@@ -0,0 +1,54 @@
+const CACHE_VERSION = "v1-20250727"; // update this on every deploy!
+const CACHE_NAME = `c2yz-cache-${CACHE_VERSION}`;
+
+const ASSETS_TO_CACHE = [
+ "/",
+ "/index.html",
+ "/styles.css",
+ "/main.js",
+ "/assets/fonts/Coiny-Regular-subset.ttf",
+ "/assets/card.png",
+ "/assets/mike-czyz.webp",
+ "/manifest.json",
+];
+
+self.addEventListener("install", (event) => {
+ event.waitUntil(
+ caches.open(CACHE_NAME).then((cache) => cache.addAll(ASSETS_TO_CACHE))
+ );
+ self.skipWaiting();
+});
+
+self.addEventListener("activate", (event) => {
+ event.waitUntil(
+ caches
+ .keys()
+ .then((keys) =>
+ Promise.all(
+ keys.filter((k) => k !== CACHE_NAME).map((k) => caches.delete(k))
+ )
+ )
+ );
+ self.clients.claim();
+});
+
+self.addEventListener("fetch", (event) => {
+ event.respondWith(
+ caches.match(event.request, { ignoreSearch: true }).then(
+ (cached) =>
+ cached ||
+ fetch(event.request)
+ .then((response) => {
+ return response;
+ })
+ .catch(() => {
+ // Optional: fallback response when offline and not cached
+ // return caches.match('/offline.html');
+ })
+ )
+ );
+});
+
+self.addEventListener("message", (event) => {
+ if (event.data === "skipWaiting") self.skipWaiting();
+});