Break blink, end of day handling
This commit is contained in:
@@ -14,6 +14,25 @@ body {
|
|||||||
font-family: 'Roboto', sans-serif;
|
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 {
|
#current {
|
||||||
flex-grow: 4;
|
flex-grow: 4;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
@@ -53,6 +72,10 @@ body {
|
|||||||
font-size: 10vmin;
|
font-size: 10vmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.event, .break {
|
||||||
|
visibility: visible !important;
|
||||||
|
}
|
||||||
|
|
||||||
.event {
|
.event {
|
||||||
color: #e28659;
|
color: #e28659;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,22 @@ function handleClientLoad() {
|
|||||||
gapi.load('client:auth2', initClient);
|
gapi.load('client:auth2', initClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findPrevious(events) {
|
||||||
|
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(events) {
|
function findCurrent(events) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
@@ -15,6 +31,22 @@ function findCurrent(events) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function anyRemaining(events) {
|
||||||
|
const current = findCurrent(events);
|
||||||
|
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(events) {
|
function findNext(events) {
|
||||||
const current = findCurrent(events);
|
const current = findCurrent(events);
|
||||||
const currentEnd = current ? new Date(current.end.dateTime).getTime() : null;
|
const currentEnd = current ? new Date(current.end.dateTime).getTime() : null;
|
||||||
@@ -31,36 +63,106 @@ function findNext(events) {
|
|||||||
return null;
|
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(events) {
|
function render(events) {
|
||||||
const curElem = document.getElementById("current");
|
const curElem = document.getElementById("current");
|
||||||
const curName = document.getElementById("currentName");
|
const curName = document.getElementById("currentName");
|
||||||
const curLeft = document.getElementById("currentLeft");
|
const curLeft = document.getElementById("currentLeft");
|
||||||
curElem.classList.remove("break", "event");
|
|
||||||
|
|
||||||
const current = findCurrent(events);
|
|
||||||
if (current) {
|
|
||||||
curElem.classList.add("event");
|
|
||||||
curName.innerText = current.summary;
|
|
||||||
const elapsed = Date.now() - new Date(current.start.dateTime).getTime();
|
|
||||||
const duration = new Date(current.end.dateTime).getTime() - new Date(current.start.dateTime).getTime();
|
|
||||||
const perc = Math.round(elapsed / duration * 100000) / 1000;
|
|
||||||
curElem.style.background = `-webkit-linear-gradient(left, #e28659 ${perc.toString()}%, transparent ${perc.toString()}%)`;
|
|
||||||
} else {
|
|
||||||
curElem.classList.add("break");
|
|
||||||
curName.innerText = '😎 Break';
|
|
||||||
}
|
|
||||||
|
|
||||||
const nextElem = document.getElementById("next");
|
const nextElem = document.getElementById("next");
|
||||||
const nextName = document.getElementById("nextName");
|
const nextName = document.getElementById("nextName");
|
||||||
nextElem.classList.remove("break", "event");
|
|
||||||
|
|
||||||
|
const current = findCurrent(events);
|
||||||
|
const prev = findPrevious(events);
|
||||||
const next = findNext(events);
|
const next = findNext(events);
|
||||||
if (next) {
|
|
||||||
nextElem.classList.add("event");
|
if (current) {
|
||||||
nextName.innerText = next.summary;
|
// 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 {
|
} 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");
|
nextElem.classList.add("break");
|
||||||
nextName.innerText = '😎 Break';
|
if (anyRemaining(events)) {
|
||||||
|
setText(nextName, "😎 Break");
|
||||||
|
} else {
|
||||||
|
setText(nextName, "✅ Done!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nextElem.classList.remove("break");
|
||||||
|
nextElem.classList.remove("event");
|
||||||
|
setText(nextName, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,9 +175,12 @@ function initClient() {
|
|||||||
ux_mode: 'redirect',
|
ux_mode: 'redirect',
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
if (gapi.auth2.getAuthInstance().isSignedIn.get()) {
|
if (gapi.auth2.getAuthInstance().isSignedIn.get()) {
|
||||||
|
const tz = timezoneOffset();
|
||||||
|
const date = new Date().toISOString().substring(0,10);
|
||||||
return gapi.client.calendar.events.list({
|
return gapi.client.calendar.events.list({
|
||||||
'calendarId': 'primary',
|
'calendarId': 'primary',
|
||||||
'timeMin': (new Date()).toISOString(),
|
'timeMin': `${date}T00:00:00${tz}`,
|
||||||
|
'timeMax': `${date}T23:59:59${tz}`,
|
||||||
'showDeleted': false,
|
'showDeleted': false,
|
||||||
'singleEvents': true,
|
'singleEvents': true,
|
||||||
'maxResults': 250,
|
'maxResults': 250,
|
||||||
|
|||||||
Reference in New Issue
Block a user