giller.dev/index.html

264 lines
No EOL
7.4 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Giller</title>
<style>
body {
background-color: #1a1a1a;
color: #aaa;
font-family: "Fira Code", "Fira Mono", "Roboto Mono", "Lucida Console", "Courier New", monospace;
font-size: 16px;
line-height: 1.5;
margin: 0;
padding: 0;
}
.info {
color: #fff;
}
#sleep {
margin-top: 2em;
}
#container {
display: flex;
height: 100vh;
justify-content: center;
align-items: center;
}
#vertical-center {
display: flex;
flex-direction: column;
width: 100vw;
}
#vertical-center,
#vertical-center>* {
align-items: center;
text-align: center;
}
#settings {
max-width: 500px;
margin: 0 auto;
height: 60vh;
padding: 0 20px;
}
#settings-notice {
position: absolute;
bottom: 5vh;
width: 100vw;
text-align: center;
color: #444;
transition-duration: 0.5s;
transition-property: opacity;
}
.hide {
opacity: 0;
}
.settings-table td {
vertical-align: top;
border-style: none;
}
</style>
</head>
<body>
<div id="settings-notice">Scroll down for settings</div>
<div id="container">
<div id="vertical-center">
Currently:
<span id="status" class="info">...</span>
<div id="sleep"></div>
</div>
</div>
<div id="settings">
<h1>Settings</h1>
<table class="settings-table">
<tr>
<td><input type="checkbox" id="notifications" name="notifications" value="notifications" /></td>
<td><label for="notifications">Enable wake up
notifications</label></td>
</tr>
</table>
</div>
<script>
const url = "https://giller.dev/g/my-status";
const notifications = [];
let userOnPage = true;
let previousStatus = undefined;
let currentStatus = undefined;
let updateRoutine = undefined;
const updateInterval = 60 * 1000;
const notificationSettingName = "wake-up-notifications";
function setText(id, text) {
document.getElementById(id).innerHTML = text;
}
function formatRemainingTime(totalSeconds) {
if (totalSeconds <= 0) {
return "should wake up anytime now"
}
const hours = Math.floor(totalSeconds / 3600);
if (hours > 24) {
return "over a day";
} else if (hours > 0) {
return hours + " hours remaining";
}
const minutes = Math.floor((totalSeconds - (hours * 3600)) / 60);
if (minutes > 0) {
return minutes + " minutes remaining";
}
const seconds = totalSeconds - (hours * 3600) - (minutes * 60);
return seconds + " seconds remaining";
}
function updateStatus() {
fetch(url)
.then(response => response.json())
.then(data => {
previousStatus = currentStatus;
currentStatus = data;
setText("status", data.status);
if (data.status.toLowerCase() === "sleeping") {
const remainingText = formatRemainingTime(data.time_until_wake);
setText("sleep", "Time until wake up:<br><span class='info'>" + remainingText + "</span>");
} else {
setText("sleep", "");
}
});
}
function dismissNotifications() {
notifications.forEach(notification => notification.close());
notifications.length = 0;
}
function hasWakenUp() {
return previousStatus && previousStatus.status.toLowerCase() === "sleeping" && currentStatus.status.toLowerCase() !== "sleeping";
}
function enableNotifications() {
if (updateRoutine) {
return;
}
// Request permission to show notifications
Notification.requestPermission().then(function (result) {
if (result === "granted") {
// Save setting
localStorage.setItem(notificationSettingName, "true");
// Enable notifications
updateRoutine = setInterval(function () {
updateStatus();
if (hasWakenUp()) {
showNotification("Max Status", "Max has woken up!");
}
}, updateInterval);
}
});
}
function disableNotifications() {
if (!updateRoutine) {
return;
}
clearInterval(updateRoutine);
updateRoutine = undefined;
dismissNotifications();
// Save setting
localStorage.setItem(notificationSettingName, "false");
}
function showNotification(title, body) {
if (userOnPage) {
return;
}
const notification = new Notification(title, {
body: body,
icon: "https://giller.dev/favicon.ico"
});
notification.onclick = function () {
window.focus();
};
notifications.push(notification);
}
function loadNotificationSetting() {
if (localStorage.getItem(notificationSettingName) === "true") {
document.getElementById("notifications").checked = true;
enableNotifications();
} else {
document.getElementById("notifications").checked = false;
disableNotifications();
}
}
// On window focus, dismiss all notifications
window.onfocus = function () {
dismissNotifications();
userOnPage = true;
};
// On window blur, enable notifications
window.onblur = function () {
userOnPage = false;
};
// On page unload, dismiss all notifications
window.onbeforeunload = function () {
dismissNotifications();
};
// On checkbox change, enable/disable notifications
document.getElementById("notifications").onchange = function () {
if (this.checked) {
enableNotifications();
} else {
disableNotifications();
}
};
// On scroll, hide settings notice
window.onscroll = function () {
const scrollPosition = window.scrollY;
if (scrollPosition > 0) {
document.getElementById("settings-notice").classList.add("hide");
} else {
document.getElementById("settings-notice").classList.remove("hide");
}
};
updateStatus();
loadNotificationSetting();
</script>
</body>
</html>