Add current clock on menubar an when clicked it show a quick view of the calendar.
Last active
October 6, 2024 19:25
-
-
Save fabriziogiordano/a22953f2bb2340b792c91f10b93637da to your computer and use it in GitHub Desktop.
HammerSpoon - Calendar Menubar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<style> | |
html { | |
background-color: transparent; | |
max-width: 300px; | |
overflow: hidden; | |
border-radius: 16px; | |
} | |
body { | |
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Helvetica", "Arial", sans-serif; | |
margin: 0; | |
padding: 10px; | |
box-sizing: border-box; | |
background-color: #1E1E1E; | |
color: white; | |
border-radius: 16px; | |
font-size: 8px; | |
color: #999; | |
border: 1px solid #555555; | |
overflow: hidden; | |
} | |
table { | |
border-collapse: collapse; | |
font-size: 10px; | |
margin: 0 auto; | |
} | |
th, | |
td { | |
text-align: center; | |
} | |
th { | |
background-color: #333333; | |
padding: 8px 0; | |
} | |
td { | |
background-color: #1E1E1E; | |
color: #ffffff; | |
width: 30px; | |
height: 30px; | |
} | |
.today { | |
background-color: #007AFF; | |
font-weight: bold; | |
color: #ffffff; | |
border-radius: 100%; | |
} | |
.nav-buttons { | |
width: 100%; | |
text-align: center; | |
margin-top: 10px; | |
display: flex; | |
flex-direction: row; | |
justify-content: space-between; | |
font-size: 6px; | |
cursor: pointer; | |
} | |
.nav-buttons button { | |
border-radius: 3px; | |
} | |
button { | |
background-color: #333333; | |
color: white; | |
border: none; | |
padding: 10px; | |
cursor: pointer; | |
} | |
button:hover { | |
background-color: #555555; | |
} | |
</style> | |
<div id="calendar"></div> | |
<div class="nav-buttons"> | |
<button onclick="changeMonth(-1)">Prev</button> | |
<button onclick="changeMonth(1)">Next</button> | |
</div> | |
<script> | |
const currentYear = new Date().getFullYear(); | |
let currentMonth = new Date().getMonth() + 1; // JavaScript months are 0-based, so we add 1 | |
function generateCalendar(year, month) { | |
const date = new Date(year, month - 1, 1); // Adjusting month to 0-based for JS Date | |
const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; | |
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; | |
const header = '<h1 style="text-align: center;">' + monthNames[month - 1] + ' ' + year + '</h1>'; | |
let table = '<table><tr>'; | |
for (var i = 0; i < 7; i++) { | |
table += '<th>' + days[i] + '</th>'; | |
} | |
table += '</tr><tr>'; | |
for (let i = 0; i < date.getDay(); i++) { | |
table += '<td></td>'; | |
} | |
const today = new Date(); | |
while (date.getMonth() === month - 1) { | |
const cellClass = (date.getDate() === today.getDate() && date.getMonth() === today.getMonth() && date.getFullYear() === today.getFullYear()) ? 'today' : ''; | |
table += '<td class="' + cellClass + '">' + date.getDate() + '</td>'; | |
if (date.getDay() === 6) { | |
table += '</tr><tr>'; | |
} | |
date.setDate(date.getDate() + 1); | |
} | |
table += '</tr></table>'; | |
document.getElementById('calendar').innerHTML = header + table; | |
} | |
// Function to change the month (either forward or backward) | |
function changeMonth(offset) { | |
currentMonth += offset; | |
// Adjust the year if necessary | |
if (currentMonth > 12) { | |
currentMonth = 1; | |
currentYear++; | |
} else if (currentMonth < 1) { | |
currentMonth = 12; | |
currentYear--; | |
} | |
// Re-generate the calendar with updated month and year | |
generateCalendar(currentYear, currentMonth); | |
} | |
// Generate the initial calendar | |
generateCalendar(currentYear, currentMonth); | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Create a menu bar item | |
local menubar = hs.menubar.new() | |
local calendarWindow = nil | |
-- Function to update the clock | |
local function updateClock() | |
-- local date = os.date("%a %b %d %H:%M"):gsub(" 0", " ") | |
-- menubar:setTitle(date) | |
menubar:setTitle("◳") | |
end | |
-- Function to sync the timer with the start of the next minute | |
local function syncTimer() | |
local now = os.time() | |
local seconds = os.date("*t", now).sec | |
local delay = 60 - seconds | |
hs.timer.doAfter(delay, function() | |
updateClock() | |
-- Set up the recurring timer after syncing | |
hs.timer.doEvery(60, updateClock) | |
end) | |
end | |
-- Function to create or toggle the calendar | |
local function toggleCalendar() | |
if calendarWindow and calendarWindow:isVisible() then | |
print("Hiding calendar window") | |
calendarWindow:delete() | |
calendarWindow = nil | |
else | |
if not calendarWindow then | |
print("Creating new calendar window") | |
-- Get the screen and frame details | |
local screen = hs.screen.mainScreen() | |
local screenFrame = screen:frame() | |
local menuBarHeight = 1 | |
-- Calculate position for the calendar window | |
local calendarWidth = 250 | |
local calendarHeight = 308 | |
local calendarX = screenFrame.x - 2 + screenFrame.w - calendarWidth -- Right-aligned | |
local calendarY = screenFrame.y + menuBarHeight -- Below the menu bar | |
calendarWindow = hs.webview.new({ | |
x = calendarX, | |
y = calendarY, | |
w = calendarWidth, | |
h = calendarHeight | |
}) | |
if not calendarWindow then | |
print("Failed to create webview") | |
return | |
end | |
-- Enable interaction with the webview | |
calendarWindow:allowTextEntry(true) | |
calendarWindow:allowGestures(true) | |
calendarWindow:allowNewWindows(false) | |
-- Set the webview window level and behavior | |
calendarWindow:level(hs.drawing.windowLevels.overlay) | |
-- calendarWindow:behavior(hs.webview.windowBehavior.canJoinAllSpaces + hs.webview.windowBehavior.stationary) | |
-- Set the HTML content for the calendar | |
local URL = "file://" .. hs.configdir .. "/calendar.html" | |
print(hs.configdir) | |
calendarWindow:url(URL) | |
calendarWindow:transparent(true) | |
end | |
print("Showing calendar window") | |
calendarWindow:show() | |
end | |
end | |
-- Set click callback for the menubar | |
menubar:setClickCallback(toggleCalendar) | |
-- Initial update and start the timer | |
updateClock() | |
syncTimer() | |
print("Script loaded successfully") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment