Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion Resources/Skins/WebView2/@Resources/Calendar/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@

<div class="calendar-body">
<div class="weekdays">
<span>Su</span><span>Mo</span><span>Tu</span><span>We</span><span>Th</span><span>Fr</span><span>Sa</span>
</div>
<div class="days" id="calendar-days">
<!-- Days will be injected here via JS -->
</div>
</div>
<div class="calendar-bottom">
<p>Hold Ctrl to Drag and Scroll to Resize.</p>
</div>
</div>
</div>
<script src="script.js"></script>
Expand Down
170 changes: 110 additions & 60 deletions Resources/Skins/WebView2/@Resources/Calendar/script.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,115 @@
// ---- Helpers ----
const loadVariable = (key, defaultValue) => {
const value = RainmeterAPI.GetVariable(String(key));
if (value.includes("#")) {
writeVariable(String(key), String(defaultValue));
return String(defaultValue);
}
return value;
};

const writeVariable = (key, value) => {
RainmeterAPI.Bang(`[!WriteKeyValue Variables "${key}" "${value}"]`);
};

const date = new Date();
const userLocale = Intl.DateTimeFormat().resolvedOptions().locale;

let locale = loadVariable('locale', userLocale);

function toggleLocale() {
locale = locale === userLocale ? 'en-US' : userLocale;
writeVariable('locale', locale);
renderWeekdays();
renderCalendar();
}

const renderWeekdays = () => {
const weekdaysContainer = document.querySelector(".weekdays");
weekdaysContainer.innerHTML = "";

const baseDate = new Date(Date.UTC(2026, 0, 5)); // Sunday

const formatter = new Intl.DateTimeFormat(locale, {
weekday: 'short'
});

for (let i = 0; i < 7; i++) {
const day = new Date(baseDate);
day.setUTCDate(baseDate.getUTCDate() + i);

const name = formatter.format(day);
weekdaysContainer.innerHTML += `<span>${name}</span>`;
}
};

const renderCalendar = () => {
date.setDate(1);

const monthDays = document.querySelector(".days");

const lastDay = new Date(
date.getFullYear(),
date.getMonth() + 1,
0
).getDate();

const prevLastDay = new Date(
date.getFullYear(),
date.getMonth(),
0
).getDate();

const firstDayIndex = date.getDay();

const lastDayIndex = new Date(
date.getFullYear(),
date.getMonth() + 1,
0
).getDay();

const nextDays = 7 - lastDayIndex - 1;

const months = [
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];

document.querySelector("#current-month").innerHTML = months[date.getMonth()];
document.querySelector("#current-year").innerHTML = date.getFullYear();

let days = "";

// Previous month's days
for (let x = firstDayIndex; x > 0; x--) {
days += `<div class="prev-date">${prevLastDay - x + 1}</div>`;
}

// Current month's days
for (let i = 1; i <= lastDay; i++) {
if (
i === new Date().getDate() &&
date.getMonth() === new Date().getMonth() &&
date.getFullYear() === new Date().getFullYear()
) {
days += `<div class="today">${i}</div>`;
} else {
days += `<div>${i}</div>`;
}
}

// Next month's days
for (let j = 1; j <= nextDays; j++) {
days += `<div class="next-date">${j}</div>`;
}

monthDays.innerHTML = days;
date.setDate(1);

const monthDays = document.querySelector(".days");

const lastDay = new Date(
date.getFullYear(),
date.getMonth() + 1,
0
).getDate();

const prevLastDay = new Date(
date.getFullYear(),
date.getMonth(),
0
).getDate();

const firstDayIndex =
(new Intl.DateTimeFormat(locale, { weekday: 'short' })
.formatToParts(date)
.find(p => p.type === 'weekday') ? date.getDay() : date.getDay());

const lastDayIndex = new Date(
date.getFullYear(),
date.getMonth() + 1,
0
).getDay();

const nextDays = 7 - lastDayIndex - 1;

// Localized month name
const monthFormatter = new Intl.DateTimeFormat(locale, { month: 'long' });

document.querySelector("#current-month").textContent =
monthFormatter.format(date);

document.querySelector("#current-year").textContent =
date.getFullYear();

let days = "";

// Previous month's days
for (let x = firstDayIndex; x > 0; x--) {
days += `<div class="prev-date">${prevLastDay - x + 1}</div>`;
}

// Current month's days
const today = new Date();

for (let i = 1; i <= lastDay; i++) {
if (
i === today.getDate() &&
date.getMonth() === today.getMonth() &&
date.getFullYear() === today.getFullYear()
) {
days += `<div class="today">${i}</div>`;
} else {
days += `<div>${i}</div>`;
}
}

// Next month's days
for (let j = 1; j <= nextDays; j++) {
days += `<div class="next-date">${j}</div>`;
}

monthDays.innerHTML = days;
};

document.querySelector("#prev-month").addEventListener("click", () => {
Expand All @@ -73,4 +122,5 @@ document.querySelector("#next-month").addEventListener("click", () => {
renderCalendar();
});

renderWeekdays();
renderCalendar();
19 changes: 15 additions & 4 deletions Resources/Skins/WebView2/@Resources/Calendar/style.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
:root {
--bg-color: #0f0f13;
--text-primary: #ffffff;
--text-secondary: #a0a0a0;
--text-secondary: #ebebeb;
--accent-color: #4facfe;
--accent-gradient: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
--glass-bg: rgba(255, 255, 255, 0.05);
--glass-bg: rgba(0, 0, 0, 0.25);
--glass-border: rgba(255, 255, 255, 0.1);
--day-hover: rgba(255, 255, 255, 0.1);
}
Expand All @@ -18,14 +18,15 @@
body {
background-color: transparent;
font-family: 'Outfit', sans-serif;
height: 100vh;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
user-select: none; /* Prevent text selection */
}


.widget-container {
position: relative;
width: 280px;
Expand Down Expand Up @@ -93,7 +94,7 @@ body {
border: 1px solid var(--glass-border);
border-radius: 14px; /* Further reduced */
padding: 10px; /* Further reduced */
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
box-shadow: 0 8px 12px 0 rgba(0, 0, 0, 0.37);
display: flex;
flex-direction: column;
}
Expand All @@ -107,6 +108,16 @@ body {
color: var(--text-primary);
}

.calendar-bottom {
position: absolute;
font-size: 0.8rem; /* Further reduced */
display: flex;
align-items: center;
color: var(--text-secondary);
bottom: -20px;
left: 15px;
}

.month-year {
font-size: 0.8rem; /* Further reduced */
font-weight: 600;
Expand Down
105 changes: 77 additions & 28 deletions Resources/Skins/WebView2/@Resources/Clock/script.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,81 @@
// ---- Helpers ----
const loadVariable = (key, defaultValue) => {
const value = RainmeterAPI.GetVariable(String(key));
if (value.includes("#")) {
writeVariable(String(key), String(defaultValue));
return String(defaultValue);
}
return value;
};

const writeVariable = (key, value) => {
RainmeterAPI.Bang(`[!WriteKeyValue Variables "${key}" "${value}"]`);
};

// ---- Variables ----
// We use Intl.DateTimeFormat().resolvedOptions to get the user's locale and timezone.
const userLocale = Intl.DateTimeFormat().resolvedOptions().locale;
const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;

let timeZone = loadVariable('timezone', userTimeZone);
let locale = loadVariable('locale', userLocale);
let format = loadVariable('format', '12h');

// ---- DOM cache ----
const dom = {
hours: document.getElementById('hours'),
minutes: document.getElementById('minutes'),
seconds: document.getElementById('seconds'),
ampm: document.getElementById('ampm'),
date: document.getElementById('date')
};

// ---- Clock logic ----
function toggleLocale() {
locale = locale === userLocale ? 'en-US' : userLocale;
writeVariable('locale', locale);
updateClock();
}

function toggleFormat() {
format = format === '12h' ? '24h' : '12h';
writeVariable('format', format);
updateClock();
}

function updateClock() {
const now = new Date();

let hours = now.getHours();
const minutes = now.getMinutes();
const seconds = now.getSeconds();
const ampm = hours >= 12 ? 'PM' : 'AM';

// Convert to 12-hour format
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'

// Pad with leading zeros
const hoursStr = hours.toString().padStart(2, '0');
const minutesStr = minutes.toString().padStart(2, '0');
const secondsStr = seconds.toString().padStart(2, '0');

// Update DOM
document.getElementById('hours').textContent = hoursStr;
document.getElementById('minutes').textContent = minutesStr;
document.getElementById('seconds').textContent = secondsStr;
document.getElementById('ampm').textContent = ampm;

// Update Date
const options = { weekday: 'long', month: 'long', day: 'numeric' };
const dateStr = now.toLocaleDateString('en-US', options);
document.getElementById('date').textContent = dateStr;
const now = new Date();

const timeFormatter = new Intl.DateTimeFormat(locale, {
timeZone,
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: format === '12h'
});

const dateFormatter = new Intl.DateTimeFormat(locale, {
timeZone,
weekday: 'long',
month: 'long',
day: 'numeric'
});

const timeParts = timeFormatter.formatToParts(now);
const dateParts = dateFormatter.formatToParts(now);

const get = (parts, type) =>
parts.find(p => p.type === type)?.value || '';

dom.hours.textContent = get(timeParts, 'hour');
dom.minutes.textContent = get(timeParts, 'minute');
dom.seconds.textContent = get(timeParts, 'second');
dom.ampm.textContent = get(timeParts, 'dayPeriod');

dom.date.textContent = dateParts.map(p => p.value).join('');
}

// Update immediately and then every second
// ---- Start clock ----
updateClock();
setInterval(updateClock, 1000);
// Update clock once a second.
setInterval(updateClock, 1000);
Loading
Loading