Move easycal to its own repo
This commit is contained in:
@@ -1,85 +0,0 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono&family=Roboto:wght@500&display=swap');
|
|
||||||
|
|
||||||
body {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
background: black;
|
|
||||||
color: white;
|
|
||||||
font-family: 'Roboto', sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.blinkSlow {
|
|
||||||
animation: blink 1.0s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.blinkFast {
|
|
||||||
animation: blink 0.5s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes blink {
|
|
||||||
0% { filter: none; }
|
|
||||||
49% { filter: none; }
|
|
||||||
50% { filter: invert(); }
|
|
||||||
100% { filter: invert(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
#current, #next {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
#current {
|
|
||||||
flex-grow: 4;
|
|
||||||
flex-shrink: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#next {
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-shrink: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#currentLeft {
|
|
||||||
font-family: 'Roboto Mono', monospace;
|
|
||||||
font-size: 10vmin;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#currentName {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 15vmin;
|
|
||||||
mix-blend-mode: difference;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nextTitle {
|
|
||||||
font-size: 7vmin;
|
|
||||||
}
|
|
||||||
|
|
||||||
#nextName {
|
|
||||||
text-align: center;
|
|
||||||
font-size: 10vmin;
|
|
||||||
}
|
|
||||||
|
|
||||||
.event, .break {
|
|
||||||
visibility: visible !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.event {
|
|
||||||
color: #e28659;
|
|
||||||
}
|
|
||||||
|
|
||||||
.break {
|
|
||||||
color: #f9cf41;
|
|
||||||
}
|
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
let events = [];
|
|
||||||
|
|
||||||
function handleClientLoad() {
|
|
||||||
gapi.load('client:auth2', initClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
function findPrevious() {
|
|
||||||
const now = Date.now();
|
|
||||||
let max = null;
|
|
||||||
let maxTime = 0;
|
|
||||||
|
|
||||||
for (const event of events) {
|
|
||||||
const end = new Date(event.end.dateTime).getTime();
|
|
||||||
if (end <= now && (!max || end >= maxTime)) {
|
|
||||||
max = event;
|
|
||||||
maxTime = end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findCurrent() {
|
|
||||||
const now = Date.now();
|
|
||||||
for (const event of events) {
|
|
||||||
const start = new Date(event.start.dateTime).getTime();
|
|
||||||
const end = new Date(event.end.dateTime).getTime();
|
|
||||||
if (start <= now && end >= now) {
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function anyRemaining() {
|
|
||||||
const current = findCurrent();
|
|
||||||
const currentEnd = current ? new Date(current.end.dateTime).getTime() : null;
|
|
||||||
|
|
||||||
const now = Date.now();
|
|
||||||
for (const event of events) {
|
|
||||||
const start = new Date(event.start.dateTime).getTime();
|
|
||||||
const end = new Date(event.end.dateTime).getTime();
|
|
||||||
if (start >= now) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findNext() {
|
|
||||||
const current = findCurrent();
|
|
||||||
const currentEnd = current ? new Date(current.end.dateTime).getTime() : null;
|
|
||||||
|
|
||||||
const now = Date.now();
|
|
||||||
for (const event of events) {
|
|
||||||
const start = new Date(event.start.dateTime).getTime();
|
|
||||||
const end = new Date(event.end.dateTime).getTime();
|
|
||||||
if (start >= now && (!current || currentEnd == start)) {
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setText(elem, text) {
|
|
||||||
if (elem.innerText != text) {
|
|
||||||
elem.innerText = text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setLeft(elem, end) {
|
|
||||||
const now = Date.now();
|
|
||||||
const left = Math.round((new Date(end).getTime() - now) / 1000);
|
|
||||||
const hours = Math.floor(left / 3600);
|
|
||||||
const minutes = Math.floor((left % 3600) / 60);
|
|
||||||
const seconds = left % 60;
|
|
||||||
|
|
||||||
let text = `${minutes.toString().padStart(2, '0')}m${seconds.toString().padStart(2, '0')}s`;
|
|
||||||
|
|
||||||
if (hours > 0) {
|
|
||||||
text = `${hours.toString()}h${text}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
setText(elem, text);
|
|
||||||
|
|
||||||
if (left < 30) {
|
|
||||||
document.body.classList.remove("blinkSlow");
|
|
||||||
document.body.classList.add("blinkFast");
|
|
||||||
} else if (left < 60) {
|
|
||||||
document.body.classList.remove("blinkFast");
|
|
||||||
document.body.classList.add("blinkSlow");
|
|
||||||
} else {
|
|
||||||
document.body.classList.remove("blinkSlow", "blinkFast");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setProgress(elem, start, end) {
|
|
||||||
const elapsed = Date.now() - new Date(start).getTime();
|
|
||||||
const duration = new Date(end).getTime() - new Date(start).getTime();
|
|
||||||
const perc = Math.round(elapsed / duration * 100000) / 1000;
|
|
||||||
elem.style.background = `-webkit-linear-gradient(left, #e28659 ${perc.toString()}%, transparent ${perc.toString()}%)`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function timezoneOffset() {
|
|
||||||
const offset = new Date().getTimezoneOffset();
|
|
||||||
return `${offset > 0 ? '-' : '+'}${Math.floor(offset / 60).toString().padStart(2, '0')}:${(offset % 60).toString().padStart(2, '0')}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function render() {
|
|
||||||
const curElem = document.getElementById("current");
|
|
||||||
const curName = document.getElementById("currentName");
|
|
||||||
const curLeft = document.getElementById("currentLeft");
|
|
||||||
const nextElem = document.getElementById("next");
|
|
||||||
const nextName = document.getElementById("nextName");
|
|
||||||
|
|
||||||
const current = findCurrent();
|
|
||||||
const prev = findPrevious();
|
|
||||||
const next = findNext();
|
|
||||||
|
|
||||||
if (current) {
|
|
||||||
// Currently in an event
|
|
||||||
curElem.classList.remove("break");
|
|
||||||
curElem.classList.add("event");
|
|
||||||
setText(curName, current.summary);
|
|
||||||
setProgress(curElem, current.start.dateTime, current.end.dateTime);
|
|
||||||
setText(curLeft, "");
|
|
||||||
document.body.classList.remove("blinkSlow", "blinkFast");
|
|
||||||
} else {
|
|
||||||
// Currently between/before/after events
|
|
||||||
curElem.classList.remove("event");
|
|
||||||
curElem.classList.add("break");
|
|
||||||
|
|
||||||
if (prev && next) {
|
|
||||||
setText(curName, "😎 Break");
|
|
||||||
setProgress(curElem, prev.end.dateTime, next.start.dateTime);
|
|
||||||
setLeft(curLeft, next.start.dateTime);
|
|
||||||
} else if (next) {
|
|
||||||
setText(curName, "😎 Break");
|
|
||||||
curElem.style.background = null;
|
|
||||||
setLeft(curLeft, next.start.dateTime);
|
|
||||||
} else {
|
|
||||||
setText(curName, "✅ Done!");
|
|
||||||
curElem.style.background = null;
|
|
||||||
setText(curLeft, "");
|
|
||||||
document.body.classList.remove("blinkSlow", "blinkFast");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next) {
|
|
||||||
nextElem.classList.remove("break");
|
|
||||||
nextElem.classList.add("event");
|
|
||||||
setText(nextName, next.summary);
|
|
||||||
} else if (current) {
|
|
||||||
nextElem.classList.remove("event");
|
|
||||||
nextElem.classList.add("break");
|
|
||||||
if (anyRemaining()) {
|
|
||||||
setText(nextName, "😎 Break");
|
|
||||||
} else {
|
|
||||||
setText(nextName, "✅ Done!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
nextElem.classList.remove("break");
|
|
||||||
nextElem.classList.remove("event");
|
|
||||||
setText(nextName, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadEvents() {
|
|
||||||
const tz = timezoneOffset();
|
|
||||||
const today = new Date();
|
|
||||||
const date = `${today.getFullYear().toString()}-${(today.getMonth() + 1).toString().padStart(2, '0')}-${today.getDate().toString().padStart(2, '0')}`;
|
|
||||||
return gapi.client.calendar.events.list({
|
|
||||||
'calendarId': 'primary',
|
|
||||||
'timeMin': `${date}T00:00:00${tz}`,
|
|
||||||
'timeMax': `${date}T23:59:59${tz}`,
|
|
||||||
'showDeleted': false,
|
|
||||||
'singleEvents': true,
|
|
||||||
'maxResults': 250,
|
|
||||||
'orderBy': 'startTime',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function initClient() {
|
|
||||||
gapi.client.init({
|
|
||||||
apiKey: 'AIzaSyDzNMBbLqQoSCMiug_7UbUrgaAvnoyzYYU',
|
|
||||||
clientId: '969085949455-0vtpi7g173fi63akr1o2eakp9nm1bp4i.apps.googleusercontent.com',
|
|
||||||
discoveryDocs: ['https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest'],
|
|
||||||
scope: 'https://www.googleapis.com/auth/calendar.readonly',
|
|
||||||
ux_mode: 'redirect',
|
|
||||||
}).then(() => {
|
|
||||||
if (gapi.auth2.getAuthInstance().isSignedIn.get()) {
|
|
||||||
return loadEvents();
|
|
||||||
} else {
|
|
||||||
gapi.auth2.getAuthInstance().signIn();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}).then((response) => {
|
|
||||||
events = response.result.items;
|
|
||||||
setInterval(() => render(), 250);
|
|
||||||
setInterval(() => {
|
|
||||||
loadEvents().then((response) => {
|
|
||||||
events = response.result.items;
|
|
||||||
});
|
|
||||||
}, 5 * 60 * 1000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
BIN
easycal/icon.png
BIN
easycal/icon.png
Binary file not shown.
|
Before Width: | Height: | Size: 7.2 KiB |
@@ -1,27 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>EasyCal</title>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="refresh" content="50000">
|
|
||||||
<link rel="stylesheet" href="easycal.css">
|
|
||||||
<link rel="icon" href="icon.png">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="current">
|
|
||||||
<div id="currentName"></div>
|
|
||||||
<div id="currentLeft"></div>
|
|
||||||
</div>
|
|
||||||
<div id="next">
|
|
||||||
<div id="nextTitle">Next:</div>
|
|
||||||
<div id="nextName"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="easycal.js"></script>
|
|
||||||
|
|
||||||
<script async defer src="https://apis.google.com/js/api.js"
|
|
||||||
onload="this.onload=function() {}; handleClientLoad();"
|
|
||||||
onreadystatechange="if (this.readyState === 'complete') this.onload();">
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Reference in New Issue
Block a user