From bf2c4689c66ca46c2df1a86b2a96081c753ec022 Mon Sep 17 00:00:00 2001 From: nstechbytes Date: Thu, 27 Nov 2025 08:04:34 +0500 Subject: [PATCH 1/4] Implement new Calendar and Clock Rainmeter skins using WebView2 and custom CSS. --- .../WebView2/@Resources/Calendar/style.css | 44 ++++++++-------- .../Skins/WebView2/@Resources/Clock/style.css | 52 +++++++++---------- .../Skins/WebView2/Calendar/Calendar.ini | 10 ++-- Resources/Skins/WebView2/Clock/Clock.ini | 10 ++-- 4 files changed, 58 insertions(+), 58 deletions(-) diff --git a/Resources/Skins/WebView2/@Resources/Calendar/style.css b/Resources/Skins/WebView2/@Resources/Calendar/style.css index 8a12122..6ddb68d 100644 --- a/Resources/Skins/WebView2/@Resources/Calendar/style.css +++ b/Resources/Skins/WebView2/@Resources/Calendar/style.css @@ -28,8 +28,8 @@ body { .widget-container { position: relative; - width: 280px; - height: 320px; /* Reduced from 380px */ + width: 210px; + height: 240px; /* Reduced from 320px */ display: flex; justify-content: center; align-items: center; @@ -45,26 +45,26 @@ body { } .shape-1 { - width: 160px; /* Reduced from 200px */ - height: 160px; + width: 120px; /* Further reduced for compact size */ + height: 120px; background: #764ba2; - top: -15px; - left: -15px; + top: -10px; + left: -10px; animation: float 10s infinite ease-in-out; } .shape-2 { - width: 140px; /* Reduced from 180px */ - height: 140px; + width: 105px; /* Further reduced for compact size */ + height: 105px; background: #4facfe; - bottom: -15px; - right: -15px; + bottom: -10px; + right: -10px; animation: float 12s infinite ease-in-out reverse; } @keyframes float { 0%, 100% { transform: translate(0, 0); } - 50% { transform: translate(15px, 15px); } /* Reduced movement */ + 50% { transform: translate(10px, 10px); } /* Further reduced movement */ } /* Glass Card */ @@ -77,8 +77,8 @@ body { backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid var(--glass-border); - border-radius: 18px; /* Reduced from 24px */ - padding: 15px; /* Reduced from 20px */ + border-radius: 14px; /* Further reduced */ + padding: 10px; /* Further reduced */ box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37); display: flex; flex-direction: column; @@ -89,16 +89,16 @@ body { display: flex; justify-content: space-between; align-items: center; - margin-bottom: 12px; /* Reduced from 20px */ + margin-bottom: 8px; /* Further reduced */ color: var(--text-primary); } .month-year { - font-size: 0.95rem; /* Reduced from 1.2rem */ + font-size: 0.8rem; /* Further reduced */ font-weight: 600; text-transform: capitalize; display: flex; - gap: 4px; /* Reduced from 5px */ + gap: 3px; /* Further reduced */ } #current-year { @@ -110,9 +110,9 @@ body { background: transparent; border: none; color: var(--text-secondary); - font-size: 1rem; /* Reduced from 1.2rem */ + font-size: 0.85rem; /* Further reduced */ cursor: pointer; - padding: 4px; /* Reduced from 5px */ + padding: 3px; /* Further reduced */ border-radius: 50%; transition: all 0.2s ease; display: flex; @@ -136,11 +136,11 @@ body { display: grid; grid-template-columns: repeat(7, 1fr); text-align: center; - margin-bottom: 6px; /* Reduced from 10px */ + margin-bottom: 4px; /* Further reduced */ } .weekdays span { - font-size: 0.7rem; /* Reduced from 0.85rem */ + font-size: 0.6rem; /* Further reduced */ font-weight: 500; color: var(--text-secondary); text-transform: uppercase; @@ -149,12 +149,12 @@ body { .days { display: grid; grid-template-columns: repeat(7, 1fr); - gap: 3px; /* Reduced from 5px */ + gap: 2px; /* Further reduced */ text-align: center; } .days div { - font-size: 0.8rem; /* Reduced from 0.95rem */ + font-size: 0.7rem; /* Further reduced */ color: var(--text-primary); width: 100%; aspect-ratio: 1; /* Make them square */ diff --git a/Resources/Skins/WebView2/@Resources/Clock/style.css b/Resources/Skins/WebView2/@Resources/Clock/style.css index ad874c9..6fe6dea 100644 --- a/Resources/Skins/WebView2/@Resources/Clock/style.css +++ b/Resources/Skins/WebView2/@Resources/Clock/style.css @@ -27,8 +27,8 @@ body { .widget-container { position: relative; - width: 350px; - height: 200px; + width: 280px; + height: 160px; display: flex; justify-content: center; align-items: center; @@ -53,29 +53,29 @@ body { } .blob-1 { - width: 120px; - height: 120px; + width: 95px; + height: 95px; background: var(--blob-color-1); - top: 20px; - left: 40px; + top: 15px; + left: 30px; animation-delay: 0s; } .blob-2 { - width: 150px; - height: 150px; + width: 120px; + height: 120px; background: var(--blob-color-2); - bottom: 20px; - right: 40px; + bottom: 15px; + right: 30px; animation-delay: -2s; } .blob-3 { - width: 100px; - height: 100px; + width: 80px; + height: 80px; background: var(--blob-color-3); - bottom: 40px; - left: 80px; + bottom: 30px; + left: 65px; animation-delay: -4s; } @@ -84,10 +84,10 @@ body { transform: translate(0, 0) scale(1); } 33% { - transform: translate(30px, -50px) scale(1.1); + transform: translate(25px, -40px) scale(1.1); } 66% { - transform: translate(-20px, 20px) scale(0.9); + transform: translate(-15px, 15px) scale(0.9); } 100% { transform: translate(0, 0) scale(1); @@ -104,7 +104,7 @@ body { backdrop-filter: blur(15px); -webkit-backdrop-filter: blur(15px); border: 1px solid var(--glass-border); - border-radius: 20px; + border-radius: 16px; display: flex; justify-content: center; align-items: center; @@ -121,19 +121,19 @@ body { align-items: baseline; justify-content: center; line-height: 1; - margin-bottom: 5px; + margin-bottom: 4px; } #hours, #minutes { - font-size: 4rem; + font-size: 3.2rem; font-weight: 700; text-shadow: 0 2px 10px rgba(0,0,0,0.2); } .colon { - font-size: 3rem; + font-size: 2.4rem; font-weight: 300; - margin: 0 5px; + margin: 0 4px; animation: blink 1s infinite; } @@ -141,25 +141,25 @@ body { display: flex; flex-direction: column; align-items: flex-start; - margin-left: 10px; - font-size: 1rem; + margin-left: 8px; + font-size: 0.85rem; font-weight: 500; } #seconds { color: var(--text-secondary); - font-size: 1.2rem; + font-size: 1rem; } #ampm { - font-size: 0.8rem; + font-size: 0.7rem; color: var(--text-secondary); text-transform: uppercase; margin-top: 2px; } .date { - font-size: 1rem; + font-size: 0.85rem; font-weight: 300; color: var(--text-secondary); letter-spacing: 1px; diff --git a/Resources/Skins/WebView2/Calendar/Calendar.ini b/Resources/Skins/WebView2/Calendar/Calendar.ini index 46a2c6d..b4acfdb 100644 --- a/Resources/Skins/WebView2/Calendar/Calendar.ini +++ b/Resources/Skins/WebView2/Calendar/Calendar.ini @@ -14,14 +14,14 @@ License=MIT Measure=Plugin Plugin=WebView2 URL=#@#Calendar\index.html -W=320 -H=400 -X=25 -Y=25 +W=260 +H=300 +X=15 +Y=15 ; ======================================== ; Background ; ======================================== [Background_Shape] Meter=Shape -Shape=Rectangle 0,0,350,450 | StrokeWidth 0 | FillColor 0,0,0,1 +Shape=Rectangle 0,0,310,330 | StrokeWidth 0 | FillColor 0,0,0,1 diff --git a/Resources/Skins/WebView2/Clock/Clock.ini b/Resources/Skins/WebView2/Clock/Clock.ini index 31af180..9ba8325 100644 --- a/Resources/Skins/WebView2/Clock/Clock.ini +++ b/Resources/Skins/WebView2/Clock/Clock.ini @@ -14,14 +14,14 @@ License=MIT Measure=Plugin Plugin=WebView2 URL=#@#Clock\index.html -W=350 -H=200 -X=25 -Y=25 +W=280 +H=160 +X=15 +Y=15 ; ======================================== ; Background ; ======================================== [Background_Shape] Meter=Shape -Shape=Rectangle 0,0,400,250 | StrokeWidth 0 | FillColor 0,0,0,1 +Shape=Rectangle 0,0,310,190 | StrokeWidth 0 | FillColor 0,0,0,1 From 876f2df61b9e3d46803e68c0c5fcd9807f86e2b5 Mon Sep 17 00:00:00 2001 From: nstechbytes Date: Thu, 27 Nov 2025 09:05:32 +0500 Subject: [PATCH 2/4] Add new Weather and Calendar Rainmeter skins with their respective WebView2 web resources. --- .../WebView2/@Resources/Calendar/index.html | 6 +- .../WebView2/@Resources/Calendar/style.css | 20 +- .../WebView2/@Resources/Weather/README.md | 54 ++++ .../WebView2/@Resources/Weather/index.html | 84 ++++++ .../WebView2/@Resources/Weather/script.js | 157 ++++++++++ .../WebView2/@Resources/Weather/style.css | 277 ++++++++++++++++++ .../Skins/WebView2/Calendar/Calendar.ini | 7 +- Resources/Skins/WebView2/Weather/Weather.ini | 27 ++ 8 files changed, 623 insertions(+), 9 deletions(-) create mode 100644 Resources/Skins/WebView2/@Resources/Weather/README.md create mode 100644 Resources/Skins/WebView2/@Resources/Weather/index.html create mode 100644 Resources/Skins/WebView2/@Resources/Weather/script.js create mode 100644 Resources/Skins/WebView2/@Resources/Weather/style.css create mode 100644 Resources/Skins/WebView2/Weather/Weather.ini diff --git a/Resources/Skins/WebView2/@Resources/Calendar/index.html b/Resources/Skins/WebView2/@Resources/Calendar/index.html index 3e259a1..bd3ba6b 100644 --- a/Resources/Skins/WebView2/@Resources/Calendar/index.html +++ b/Resources/Skins/WebView2/@Resources/Calendar/index.html @@ -14,8 +14,10 @@
-
-
+
+
+
+
diff --git a/Resources/Skins/WebView2/@Resources/Calendar/style.css b/Resources/Skins/WebView2/@Resources/Calendar/style.css index 6ddb68d..aa3420f 100644 --- a/Resources/Skins/WebView2/@Resources/Calendar/style.css +++ b/Resources/Skins/WebView2/@Resources/Calendar/style.css @@ -28,14 +28,28 @@ body { .widget-container { position: relative; - width: 210px; - height: 240px; /* Reduced from 320px */ + width: 280px; + height: 295px; /* Match Weather height */ display: flex; justify-content: center; align-items: center; + border-radius: 20px; /* Force rounded corners for entire widget */ + overflow: hidden; /* Clip everything to rounded shape */ } /* Abstract Background Shapes */ +.shape-container { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 90%; /* Match card width */ + height: 85%; /* Match card height */ + border-radius: 14px; /* Match card border-radius */ + overflow: hidden; + z-index: 0; +} + .bg-shape { position: absolute; border-radius: 50%; @@ -72,7 +86,7 @@ body { position: relative; z-index: 1; width: 90%; - height: 90%; + height: 85%; /* Reduced to match Weather and prevent clipping */ background: var(--glass-bg); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); diff --git a/Resources/Skins/WebView2/@Resources/Weather/README.md b/Resources/Skins/WebView2/@Resources/Weather/README.md new file mode 100644 index 0000000..b438ddc --- /dev/null +++ b/Resources/Skins/WebView2/@Resources/Weather/README.md @@ -0,0 +1,54 @@ +# Weather Widget Setup + +## Getting Your API Key + +1. Go to [OpenWeatherMap](https://openweathermap.org/api) +2. Sign up for a free account +3. Navigate to "API keys" section +4. Copy your API key + +## Configuration + +Open `script.js` and update the following: + +```javascript +const API_KEY = 'YOUR_API_KEY'; // Replace with your actual API key +const USE_GEOLOCATION = true; // Set to false to use manual coordinates + +// If using manual coordinates, update these: +const MANUAL_LAT = 31.5204; // Your latitude +const MANUAL_LON = 74.3587; // Your longitude +``` + +## Features + +- **Auto-location detection**: Uses browser geolocation API +- **Manual coordinates**: Fallback option if geolocation fails +- **Real-time weather**: Temperature, humidity, wind speed, feels like +- **Weather icons**: Dynamic icons based on current conditions +- **Auto-refresh**: Updates every 10 minutes +- **Beautiful UI**: Glassmorphic design with animated background + +## Weather Icons + +The widget displays different icons based on weather conditions: +- ☀️ Clear sky +- ☁️ Clouds +- 🌧️ Rain +- ⛈️ Thunderstorm +- ❄️ Snow +- 🌫️ Mist/Fog + +## Troubleshooting + +**"Please set your OpenWeatherMap API key"** +- You need to replace `YOUR_API_KEY` with your actual API key + +**"Unable to fetch weather data"** +- Check your internet connection +- Verify your API key is correct +- Make sure your API key is activated (can take a few minutes) + +**Location not accurate** +- Enable browser location permissions +- Or set manual coordinates in `script.js` diff --git a/Resources/Skins/WebView2/@Resources/Weather/index.html b/Resources/Skins/WebView2/@Resources/Weather/index.html new file mode 100644 index 0000000..a3c5b4d --- /dev/null +++ b/Resources/Skins/WebView2/@Resources/Weather/index.html @@ -0,0 +1,84 @@ + + + + + + Weather Widget + + + + + + + + +
+ +
+
+
+
+
+ +
+ +
+ +

Getting weather...

+
+ + + + + + +
+
+ + + diff --git a/Resources/Skins/WebView2/@Resources/Weather/script.js b/Resources/Skins/WebView2/@Resources/Weather/script.js new file mode 100644 index 0000000..2421c1d --- /dev/null +++ b/Resources/Skins/WebView2/@Resources/Weather/script.js @@ -0,0 +1,157 @@ +// Weather Widget Script +const API_KEY = 'd87d34d2cddf097a3710c1627a0d024d'; // Users can get free API key from openweathermap.org +const USE_GEOLOCATION = false; // Set to true to use browser geolocation (may not work in WebView2) + +// Manual coordinates - UPDATE THESE TO YOUR LOCATION +const MANUAL_LAT = 29.712885630493965; +const MANUAL_LON = 72.4520053233683; + +// DOM Elements +const loadingEl = document.getElementById('loading'); +const errorEl = document.getElementById('error'); +const errorMessageEl = document.getElementById('error-message'); +const weatherContentEl = document.getElementById('weather-content'); +const cityEl = document.getElementById('city'); +const tempEl = document.getElementById('temp'); +const descriptionEl = document.getElementById('description'); +const weatherIconEl = document.getElementById('weather-icon'); +const humidityEl = document.getElementById('humidity'); +const windEl = document.getElementById('wind'); +const feelsLikeEl = document.getElementById('feels-like'); + +// Weather icon mapping +const weatherIcons = { + '01d': 'ph-sun', // clear sky day + '01n': 'ph-moon', // clear sky night + '02d': 'ph-cloud-sun', // few clouds day + '02n': 'ph-cloud-moon', // few clouds night + '03d': 'ph-cloud', // scattered clouds + '03n': 'ph-cloud', + '04d': 'ph-clouds', // broken clouds + '04n': 'ph-clouds', + '09d': 'ph-cloud-rain', // shower rain + '09n': 'ph-cloud-rain', + '10d': 'ph-cloud-rain', // rain day + '10n': 'ph-cloud-rain', // rain night + '11d': 'ph-lightning', // thunderstorm + '11n': 'ph-lightning', + '13d': 'ph-snowflake', // snow + '13n': 'ph-snowflake', + '50d': 'ph-wind', // mist + '50n': 'ph-wind' +}; + +// Show error +function showError(message) { + if (loadingEl) loadingEl.classList.add('hidden'); + if (weatherContentEl) weatherContentEl.classList.add('hidden'); + if (errorMessageEl) errorMessageEl.textContent = message; + if (errorEl) errorEl.classList.remove('hidden'); +} + +// Show weather +function showWeather() { + if (loadingEl) loadingEl.classList.add('hidden'); + if (errorEl) errorEl.classList.add('hidden'); + if (weatherContentEl) weatherContentEl.classList.remove('hidden'); +} + +// Update weather icon +function updateWeatherIcon(iconCode) { + const iconClass = weatherIcons[iconCode] || 'ph-sun'; + if (weatherIconEl) { + weatherIconEl.innerHTML = ``; + } +} + +// Fetch weather data +async function fetchWeather(lat, lon) { + try { + const url = `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&units=metric&appid=${API_KEY}`; + + const response = await fetch(url, { + method: 'GET', + mode: 'cors', + cache: 'no-cache', + credentials: 'omit' // Don't send credentials to avoid tracking prevention + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + + // Update UI with null checks + if (cityEl) cityEl.textContent = `${data.name}, ${data.sys.country}`; + if (tempEl) tempEl.textContent = Math.round(data.main.temp); + if (descriptionEl) descriptionEl.textContent = data.weather[0].description; + if (humidityEl) humidityEl.textContent = `${data.main.humidity}%`; + if (windEl) windEl.textContent = `${Math.round(data.wind.speed * 3.6)} km/h`; + if (feelsLikeEl) feelsLikeEl.textContent = `${Math.round(data.main.feels_like)}°`; + + updateWeatherIcon(data.weather[0].icon); + showWeather(); + + } catch (error) { + console.error('Error fetching weather:', error); + showError(`Error: ${error.message}`); + } +} + +// Get user location +function getUserLocation() { + if (USE_GEOLOCATION && navigator.geolocation) { + // Try geolocation with timeout + const options = { + enableHighAccuracy: false, + timeout: 5000, + maximumAge: 0 + }; + + navigator.geolocation.getCurrentPosition( + (position) => { + const lat = position.coords.latitude; + const lon = position.coords.longitude; + fetchWeather(lat, lon); + }, + (error) => { + console.warn('Geolocation failed, using manual coordinates:', error.message); + // Fallback to manual coordinates + fetchWeather(MANUAL_LAT, MANUAL_LON); + }, + options + ); + } else { + // Use manual coordinates + fetchWeather(MANUAL_LAT, MANUAL_LON); + } +} + +// Initialize +function init() { + try { + // Check if API key is set + if (API_KEY === 'YOUR_API_KEY') { + showError('Please set your API key in script.js'); + return; + } + + // Initial fetch + getUserLocation(); + + // Refresh weather every 10 minutes + setInterval(getUserLocation, 600000); + + } catch (error) { + console.error('Initialization error:', error); + showError('Failed to initialize widget'); + } +} + +// Wait for DOM to be ready +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); +} else { + init(); +} diff --git a/Resources/Skins/WebView2/@Resources/Weather/style.css b/Resources/Skins/WebView2/@Resources/Weather/style.css new file mode 100644 index 0000000..e0c2b93 --- /dev/null +++ b/Resources/Skins/WebView2/@Resources/Weather/style.css @@ -0,0 +1,277 @@ +:root { + --bg-color: #0f0f13; + --text-primary: #ffffff; + --text-secondary: #a0a0a0; + --accent-blue: #4facfe; + --accent-cyan: #00f2fe; + --accent-purple: #a18cd1; + --glass-bg: rgba(255, 255, 255, 0.05); + --glass-border: rgba(255, 255, 255, 0.1); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + background-color: transparent; + font-family: 'Outfit', sans-serif; + height: 100vh; + display: flex; + justify-content: center; + align-items: center; + overflow: hidden; + user-select: none; +} + +.widget-container { + position: relative; + width: 280px; + height: 300px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 20px; /* Force rounded corners for entire widget */ + overflow: hidden; /* Clip everything to rounded shape */ +} + +/* Animated Background */ +.weather-bg { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 90%; /* Match card width */ + height: 85%; /* Match card height */ + z-index: 0; + overflow: hidden; + border-radius: 16px; /* Match card border-radius */ +} + +.particle { + position: absolute; + border-radius: 50%; + opacity: 0.5; + filter: blur(25px); +} + +.particle-1 { + width: 100px; + height: 100px; + background: var(--accent-blue); + top: -20px; + left: -20px; + animation: float-particle 10s infinite ease-in-out; +} + +.particle-2 { + width: 120px; + height: 120px; + background: var(--accent-cyan); + bottom: -30px; + right: -30px; + animation: float-particle 12s infinite ease-in-out reverse; +} + +.particle-3 { + width: 80px; + height: 80px; + background: var(--accent-purple); + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + animation: pulse 8s infinite ease-in-out; +} + +@keyframes float-particle { + 0%, 100% { transform: translate(0, 0); } + 50% { transform: translate(15px, 15px); } +} + +@keyframes pulse { + 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.5; } + 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.7; } +} + +/* Weather Card */ +.weather-card { + position: relative; + z-index: 1; + width: 90%; + height: 85%; + background: var(--glass-bg); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border: 1px solid var(--glass-border); + border-radius: 16px; + padding: 12px; + box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37); + display: flex; + flex-direction: column; +} + +/* Loading & Error States */ +.loading, .error { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + color: var(--text-primary); + gap: 8px; +} + +.loading i, .error i { + font-size: 2rem; + color: var(--accent-blue); +} + +.error i { + color: #ff6b6b; +} + +.loading p, .error p { + font-size: 0.85rem; + color: var(--text-secondary); +} + +.spin { + animation: spin 1s linear infinite; +} + +@keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +.hidden { + display: none !important; +} + +/* Weather Content */ +.weather-content { + display: flex; + flex-direction: column; + height: 100%; +} + +.location { + display: flex; + align-items: center; + gap: 5px; + color: var(--text-secondary); + font-size: 0.75rem; + margin-bottom: 8px; +} + +.location i { + font-size: 0.85rem; +} + +/* Main Weather Section */ +.main-weather { + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin-bottom: 10px; +} + +.temp-section { + display: flex; + align-items: center; + gap: 15px; + margin-bottom: 5px; +} + +.temperature { + display: flex; + align-items: baseline; + color: var(--text-primary); +} + +#temp { + font-size: 3rem; + font-weight: 700; + line-height: 1; +} + +.unit { + font-size: 1.5rem; + font-weight: 300; + margin-left: 3px; +} + +.weather-icon { + font-size: 2.5rem; + color: var(--accent-blue); + display: flex; + align-items: center; + justify-content: center; +} + +.description { + font-size: 0.9rem; + color: var(--text-secondary); + text-transform: capitalize; + text-align: center; +} + +/* Weather Details */ +.weather-details { + display: flex; + flex-direction: column; + gap: 12px; + padding-top: 15px; + border-top: 1px solid var(--glass-border); + margin-top: auto; +} + +.detail-item { + display: flex; + flex-direction: row; + align-items: center; + padding: 0 10px; + width: 100%; +} + +.detail-item i { + font-size: 1.2rem; + color: var(--accent-cyan); + width: 25px; +} + +.detail-info { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + width: 100%; + margin-left: 5px; +} + +.detail-label { + font-size: 0.85rem; + color: var(--text-secondary); + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.detail-value { + font-size: 0.9rem; + color: var(--text-primary); + font-weight: 500; +} + +/* Weather Icon Animations */ +.weather-icon i { + animation: icon-float 3s ease-in-out infinite; +} + +@keyframes icon-float { + 0%, 100% { transform: translateY(0px); } + 50% { transform: translateY(-5px); } +} diff --git a/Resources/Skins/WebView2/Calendar/Calendar.ini b/Resources/Skins/WebView2/Calendar/Calendar.ini index b4acfdb..5179e61 100644 --- a/Resources/Skins/WebView2/Calendar/Calendar.ini +++ b/Resources/Skins/WebView2/Calendar/Calendar.ini @@ -14,8 +14,8 @@ License=MIT Measure=Plugin Plugin=WebView2 URL=#@#Calendar\index.html -W=260 -H=300 +W=280 +H=350 X=15 Y=15 ; ======================================== @@ -23,5 +23,4 @@ Y=15 ; ======================================== [Background_Shape] Meter=Shape -Shape=Rectangle 0,0,310,330 | StrokeWidth 0 | FillColor 0,0,0,1 - +Shape=Rectangle 0,0,310,400 | StrokeWidth 0 | FillColor 0,0,0,1 diff --git a/Resources/Skins/WebView2/Weather/Weather.ini b/Resources/Skins/WebView2/Weather/Weather.ini new file mode 100644 index 0000000..99eff65 --- /dev/null +++ b/Resources/Skins/WebView2/Weather/Weather.ini @@ -0,0 +1,27 @@ +[Rainmeter] +Update=1000 + +[Metadata] +Name=Weather +Author=nstechbytes +Information=Weather Widget using WebView2 +Version=0.0.1 +License=MIT +; ======================================== +; Measure +; ======================================== +[WebView2] +Measure=Plugin +Plugin=WebView2 +URL=#@#Weather\index.html +W=280 +H=350 +X=15 +Y=15 +; ======================================== +; Background +; ======================================== +[Background_Shape] +Meter=Shape +Shape=Rectangle 0,0,310,400 | StrokeWidth 0 | FillColor 0,0,0,1 + From 39888465000cf5643d65eed1e2be02df37c2b0df Mon Sep 17 00:00:00 2001 From: nstechbytes Date: Thu, 27 Nov 2025 14:03:26 +0500 Subject: [PATCH 3/4] implement new Islamic Date widget with WebView2, API integration, and styling --- .../@Resources/IslamicDate/index.html | 41 +++++ .../WebView2/@Resources/IslamicDate/script.js | 91 ++++++++++ .../WebView2/@Resources/IslamicDate/style.css | 170 ++++++++++++++++++ .../WebView2/IslamicDate/IslamicDate.ini | 27 +++ 4 files changed, 329 insertions(+) create mode 100644 Resources/Skins/WebView2/@Resources/IslamicDate/index.html create mode 100644 Resources/Skins/WebView2/@Resources/IslamicDate/script.js create mode 100644 Resources/Skins/WebView2/@Resources/IslamicDate/style.css create mode 100644 Resources/Skins/WebView2/IslamicDate/IslamicDate.ini diff --git a/Resources/Skins/WebView2/@Resources/IslamicDate/index.html b/Resources/Skins/WebView2/@Resources/IslamicDate/index.html new file mode 100644 index 0000000..c8d7436 --- /dev/null +++ b/Resources/Skins/WebView2/@Resources/IslamicDate/index.html @@ -0,0 +1,41 @@ + + + + + + Islamic Date Widget + + + + + + + + +
+ +
+
+
+
+
+ +
+
+ +
+
+ +
+
1
+
+ + +
Muharram
+
1446 AH
+
+
+
+ + + diff --git a/Resources/Skins/WebView2/@Resources/IslamicDate/script.js b/Resources/Skins/WebView2/@Resources/IslamicDate/script.js new file mode 100644 index 0000000..09ad919 --- /dev/null +++ b/Resources/Skins/WebView2/@Resources/IslamicDate/script.js @@ -0,0 +1,91 @@ +// Islamic Date Widget Script using Aladhan API + +// Islamic month names +const islamicMonths = [ + 'Muharram', + 'Safar', + 'Rabi\' al-Awwal', + 'Rabi\' al-Thani', + 'Jumada al-Awwal', + 'Jumada al-Thani', + 'Rajab', + 'Sha\'ban', + 'Ramadan', + 'Shawwal', + 'Dhu al-Qi\'dah', + 'Dhu al-Hijjah' +]; + +// Fetch Islamic date from API +async function fetchIslamicDate() { + try { + // Get current date + const now = new Date(); + const day = now.getDate(); + const month = now.getMonth() + 1; // JavaScript months are 0-indexed + const year = now.getFullYear(); + + // Fetch from Aladhan API with Pakistan calculation method + // method=1 uses University of Islamic Sciences, Karachi (Pakistan) + const response = await fetch( + `https://api.aladhan.com/v1/gToH/${day}-${month}-${year}?adjustment=1`, + { + method: 'GET', + mode: 'cors', + cache: 'no-cache', + credentials: 'omit' + } + ); + + if (!response.ok) { + throw new Error('Failed to fetch Islamic date'); + } + + const data = await response.json(); + + if (data.code === 200 && data.data && data.data.hijri) { + const hijri = data.data.hijri; + + // Update UI + document.getElementById('hijri-day').textContent = hijri.day; + document.getElementById('hijri-month').textContent = hijri.month.en; + document.getElementById('hijri-year').textContent = `${hijri.year} AH`; + + console.log('Islamic date updated:', hijri.day, hijri.month.en, hijri.year); + } else { + throw new Error('Invalid API response'); + } + + } catch (error) { + console.error('Error fetching Islamic date:', error); + // Fallback to showing error or default values + document.getElementById('hijri-day').textContent = '--'; + document.getElementById('hijri-month').textContent = 'Error'; + document.getElementById('hijri-year').textContent = '---- AH'; + } +} + +// Initialize +function init() { + // Initial fetch + fetchIslamicDate(); + + // Update once per day at midnight + const now = new Date(); + const tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1); + const msUntilMidnight = tomorrow - now; + + // Set timeout for midnight, then update daily + setTimeout(() => { + fetchIslamicDate(); + // Update every 24 hours after that + setInterval(fetchIslamicDate, 24 * 60 * 60 * 1000); + }, msUntilMidnight); +} + +// Wait for DOM to be ready +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); +} else { + init(); +} diff --git a/Resources/Skins/WebView2/@Resources/IslamicDate/style.css b/Resources/Skins/WebView2/@Resources/IslamicDate/style.css new file mode 100644 index 0000000..fe14778 --- /dev/null +++ b/Resources/Skins/WebView2/@Resources/IslamicDate/style.css @@ -0,0 +1,170 @@ +:root { + --bg-color: #0f0f13; + --text-primary: #ffffff; + --text-secondary: #a0a0a0; + --accent-purple: #764ba2; + --accent-blue: #4facfe; + --accent-cyan: #00f2fe; + --glass-bg: rgba(255, 255, 255, 0.05); + --glass-border: rgba(255, 255, 255, 0.1); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + background-color: transparent; + font-family: 'Outfit', sans-serif; + height: 100vh; + display: flex; + justify-content: center; + align-items: center; + overflow: hidden; + user-select: none; +} + +.widget-container { + position: relative; + width: 280px; + height: 160px; + display: flex; + justify-content: center; + align-items: center; + border-radius: 20px; + overflow: hidden; +} + +/* Abstract Background Shapes */ +.shape-container { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 90%; + height: 80%; + border-radius: 16px; + overflow: hidden; + z-index: 0; +} + +.bg-shape { + position: absolute; + border-radius: 50%; + filter: blur(25px); + opacity: 0.6; + z-index: 0; +} + +.shape-1 { + width: 95px; + height: 95px; + background: #764ba2; + top: 10px; + left: 20px; + animation: float 10s infinite ease-in-out; +} + +.shape-2 { + width: 110px; + height: 110px; + background: #4facfe; + bottom: 10px; + right: 20px; + animation: float 12s infinite ease-in-out reverse; +} + +.shape-3 { + width: 80px; + height: 80px; + background: #00f2fe; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + animation: pulse 8s infinite ease-in-out; +} + +@keyframes float { + 0%, 100% { transform: translate(0, 0); } + 50% { transform: translate(10px, 10px); } +} + +@keyframes pulse { + 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.6; } + 50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.8; } +} + +/* Glass Card */ +.islamic-card { + position: relative; + z-index: 1; + width: 90%; + height: 80%; + background: var(--glass-bg); + backdrop-filter: blur(15px); + -webkit-backdrop-filter: blur(15px); + border: 1px solid var(--glass-border); + border-radius: 16px; + display: flex; + justify-content: center; + align-items: center; + box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37); +} + +/* Content Wrapper - Centered Layout */ +.content-wrapper { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + text-align: center; +} + +/* Top Row - Icon and Day */ +.top-row { + display: flex; + align-items: center; + gap: 12px; +} + +/* Icon Container */ +.icon-container { + display: flex; + align-items: center; +} + +.icon-container i { + font-size: 3rem; + color: var(--text-primary); +} + + +/* Date Elements */ +.hijri-day { + font-size: 3.5rem; + font-weight: 700; + color: var(--text-primary); + line-height: 1; + text-shadow: 0 2px 10px rgba(0,0,0,0.2); +} + +.hijri-month { + font-size: 1.2rem; + font-weight: 600; + color: var(--text-primary); + line-height: 1; +} + +.hijri-year { + font-size: 0.8rem; + font-weight: 300; + color: var(--text-secondary); + letter-spacing: 1.5px; + text-transform: uppercase; +} + + + + diff --git a/Resources/Skins/WebView2/IslamicDate/IslamicDate.ini b/Resources/Skins/WebView2/IslamicDate/IslamicDate.ini new file mode 100644 index 0000000..05573e0 --- /dev/null +++ b/Resources/Skins/WebView2/IslamicDate/IslamicDate.ini @@ -0,0 +1,27 @@ +[Rainmeter] +Update=1000 + +[Metadata] +Name=Islamic Date +Author=nstechbytes +Information=Islamic (Hijri) Date Widget using WebView2 +Version=0.0.1 +License=MIT +; ======================================== +; Measure +; ======================================== +[WebView2] +Measure=Plugin +Plugin=WebView2 +URL=#@#IslamicDate\index.html +W=280 +H=160 +X=15 +Y=15 +; ======================================== +; Background +; ======================================== +[Background_Shape] +Meter=Shape +Shape=Rectangle 0,0,310,190 | StrokeWidth 0 | FillColor 0,0,0,1 + From e0fffc868061b864a77d791dee884c18500b594e Mon Sep 17 00:00:00 2001 From: nstechbytes Date: Thu, 27 Nov 2025 18:51:19 +0500 Subject: [PATCH 4/4] add new WebView2 C++ project, resource files, and update build script. --- Build-CPP.ps1 | 2 +- Resources/skin_definition.json | 4 ++-- WebView2/WebView2.rc | Bin 1624 -> 1624 bytes WebView2/WebView2.vcxproj | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Build-CPP.ps1 b/Build-CPP.ps1 index 19cfe87..c05a923 100644 --- a/Build-CPP.ps1 +++ b/Build-CPP.ps1 @@ -1,4 +1,4 @@ -#usage -----> powershell -ExecutionPolicy Bypass -Command "& {. .\Build-CPP.ps1; Dist -major 0 -minor 0 -patch 3}" +#usage -----> powershell -ExecutionPolicy Bypass -Command "& {. .\Build-CPP.ps1; Dist -major 0 -minor 0 -patch 5}" $msbuild = "C:\Program Files\Microsoft Visual Studio\2022\Community\Msbuild\Current\Bin\MSBuild.exe" function Add-RMSkinFooter { diff --git a/Resources/skin_definition.json b/Resources/skin_definition.json index 313761d..5e39e2c 100644 --- a/Resources/skin_definition.json +++ b/Resources/skin_definition.json @@ -1,6 +1,6 @@ { "skinDir": ".\\Resources\\Skins", - "version": "0.0.4", + "version": "0.0.5", "minimumVersion": "4.5", "author": "nstechbytes", "variableFiles": "", @@ -17,5 +17,5 @@ "load": "WebView2\\Clock\\Clock.ini", "headerImage": ".\\Resources\\banner.bmp", "configPrefix": "WebView2", - "output": ".\\dist\\WebView2_v0.0.4_Alpha4.rmskin" + "output": ".\\dist\\WebView2_v0.0.5_Alpha5.rmskin" } diff --git a/WebView2/WebView2.rc b/WebView2/WebView2.rc index 74aae460b08879acf302d8d724479b6241bfa196..883788c0d5ecc39b837d179fa9dd5c0c02ffdd43 100644 GIT binary patch delta 24 gcmcb?bAxBX5k}LAN9~zS8I&gbGm3APW3*xg0B;5dO#lD@ delta 24 gcmcb?bAxBX5k`}VN9~zS7?dXaGm3APW3*xg0B-3AO8@`> diff --git a/WebView2/WebView2.vcxproj b/WebView2/WebView2.vcxproj index 40d917f..dbdb55c 100644 --- a/WebView2/WebView2.vcxproj +++ b/WebView2/WebView2.vcxproj @@ -204,6 +204,9 @@ + + Static + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.