NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name GetFlow presentation mode // @namespace http://redrice.io/ // @version 0.2 // @description Enter presentation mode when entering fullscreen. Usefull for standups and such. // @author Marek ‘saji’ Augustynowicz // @copyright 2019, Marek Augustynowicz // @license MIT // @match https://app.getflow.com/organizations/* // @updateURL https://openuserjs.org/meta/saji/GetFlow_presentation_mode.meta.js // @grant none // ==/UserScript== (function() { 'use strict'; const LC_NAME = 'DAILY_TIMERS'; const TIMER_ID = 'presentationTimer'; const SUMMARY_ID = 'timesSummary'; let start = null; let prevElapsed = null; function injectStyles () { const style = document.createElement('style'); style.setAttribute('id', 'presentation-mode'); style.textContent = ` :-webkit-full-screen #app-header-wrap, :-webkit-full-screen .list-view-header-container { display: none; } :-webkit-full-screen .main-content-view { top: 0 !important; } :-webkit-full-screen { font-size: 1.25em; } :-webkit-full-screen * { font-size: 1em !important; } :-webkit-full-screen .content-view[data-view-mode="column"] .task-list-section { width: calc(100vw / 6); } .DAILY_TIMER__summary dt, .DAILY_TIMER__summary dd { display: inline; } .DAILY_TIMER__summary dt::after { content: ': '; } .DAILY_TIMER__summary dd::after { content: '\\A'; white-space: pre; } .DAILY_TIMER__summaryDT--last, .DAILY_TIMER__summaryDD--last { background-color: #fa8b54; } `; document.getElementsByTagName('head')[0].appendChild(style); } function removeTimer () { const timer = document.getElementById(TIMER_ID) if (timer) { timer.remove(); } } function addTimer () { removeTimer(); const timer = document.createElement('aside'); timer.id = TIMER_ID; timer.style = ` pointer-events: none; opacity: 0.25; font: 3em/1 Iosevka, monospace !important; position: fixed; z-index: 10000; bottom: 1ex; right: 1ex; padding: 0.1ex 0.2ex 0; background: white; border-radius: 0.5ex; `; document.body.appendChild(timer); const times = JSON.parse(localStorage.getItem(LC_NAME) || '{}'); prevElapsed = times[getTodayDateString()] || 0; start = performance.now(); updateTimer(timer); } function formatTime (elapsed) { elapsed = parseInt(elapsed / 1000, 10); const sec = elapsed % 60; const min = (elapsed - sec) / 60; return [ String(min).padStart(2, '0'), String(sec).padStart(2, '0') ].join(':'); } function getTodayDateString () { return (new Date).toLocaleDateString('pl-PL'); } function updateTimer (timer) { if (! timer.parentElement || !start) { return; } const elapsed = parseInt(performance.now() - start, 10); timer.textContent = formatTime(elapsed + prevElapsed); requestAnimationFrame(() => updateTimer(timer)); } function stopTimer () { if (start) { const elapsed = parseInt(performance.now() - start, 10); const times = JSON.parse(localStorage.getItem(LC_NAME) || '{}'); times[getTodayDateString()] = (times[getTodayDateString()] || 0) + elapsed; localStorage.setItem(LC_NAME, JSON.stringify(times)); } start = null; prevElapsed = null; } function addSummary () { const dialog = document.createElement('dialog'); dialog.id = SUMMARY_ID; dialog.style = ` white-space: pre; top: 50%; transform: translateY(-50%); z-index: 65000; font-size: 4em; font-family: monospace; `; const dl = document.createElement('dl'); dl.classList.add('DAILY_TIMER__summary'); dialog.appendChild(dl); const times = JSON.parse(localStorage.getItem(LC_NAME) || '{}'); const timesEntries = Object.entries(times); timesEntries.forEach( ([date, time], idx) => { let emoji; if (time < 10 * 60 * 1000) { emoji = '🎉'; } else if (time < 15 * 60 * 1000) { emoji = '😒'; } else if (time < 20 * 60 * 1000) { emoji = '😖'; } else { emoji = '😱'; } const dt = document.createElement('dt'); dt.textContent = date; const dd = document.createElement('dd'); dd.textContent = formatTime(time); const emojiNode = document.createTextNode(` ${emoji}`); dd.appendChild(emojiNode); if (idx === timesEntries.length - 1) { dt.classList.add('DAILY_TIMER__summaryDT--last'); dd.classList.add('DAILY_TIMER__summaryDD--last'); } dl.appendChild(dt); dl.appendChild(dd); } ); const closeButton = document.createElement('button'); closeButton.type = 'button'; closeButton.textContent = '×'; closeButton.style = ` position: absolute; top: 1ex; right: 1ex; border: none; background; black; color: white; `; closeButton.addEventListener('click', () => removeSummary()); dialog.appendChild(closeButton); document.body.appendChild(dialog); dialog.showModal(); } function removeSummary () { const summary = document.getElementById(SUMMARY_ID); if (summary) { summary.remove(); } } function handleFullscreenEnter () { removeSummary(); addTimer(); window.addEventListener('beforeunload', stopTimer); } function handleFullscreenLeave () { stopTimer(); removeTimer(); addSummary(); window.removeEventListener('beforeunload', stopTimer); } injectStyles(); document.addEventListener('fullscreenchange', () => { if (!document.isFullScreen && !document.webkitIsFullScreen) { handleFullscreenLeave(); } }); document.addEventListener('keydown', (event) => { if (event.key === 'F11') { event.preventDefault(); if (document.isFullScreen || document.webkitIsFullScreen) { document.exitFullscreen(); handleFullscreenLeave(); } else { document.documentElement.requestFullscreen(); handleFullscreenEnter(); } } }); })();