diff options
author | Norwin <noerw@users.noreply.github.com> | 2021-01-21 14:51:52 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-21 15:51:52 +0100 |
commit | b5570d3e680570343c1552bfc972b19b161209cd (patch) | |
tree | 548fbcdb9a760b47c54ac931c0180d87d08029d5 /web_src/js | |
parent | 56a89296050096df29d0a653019c194631cc6562 (diff) | |
download | gitea-b5570d3e680570343c1552bfc972b19b161209cd.tar.gz gitea-b5570d3e680570343c1552bfc972b19b161209cd.zip |
Display current stopwatch in navbar (#14122)
* add notification about running stopwatch to header
* serialize seconds, duration in stopwatches api
* ajax update stopwatch
i should get my testenv working locally...
* new variant: hover dialog
* noscript compatibility
* js: live-update stopwatch time
* js live update robustness
Diffstat (limited to 'web_src/js')
-rw-r--r-- | web_src/js/features/stopwatch.js | 91 | ||||
-rw-r--r-- | web_src/js/index.js | 2 |
2 files changed, 93 insertions, 0 deletions
diff --git a/web_src/js/features/stopwatch.js b/web_src/js/features/stopwatch.js new file mode 100644 index 0000000000..d500fb5f0f --- /dev/null +++ b/web_src/js/features/stopwatch.js @@ -0,0 +1,91 @@ +import prettyMilliseconds from 'pretty-ms'; +const {AppSubUrl, csrf, NotificationSettings} = window.config; + +let updateTimeInterval = null; // holds setInterval id when active + +export async function initStopwatch() { + const stopwatchEl = $('.active-stopwatch-trigger'); + + stopwatchEl.removeAttr('href'); // intended for noscript mode only + stopwatchEl.popup({ + position: 'bottom right', + hoverable: true, + }); + + // form handlers + $('form > button', stopwatchEl).on('click', function () { + $(this).parent().trigger('submit'); + }); + + if (!stopwatchEl || NotificationSettings.MinTimeout <= 0) { + return; + } + + const fn = (timeout) => { + setTimeout(async () => { + await updateStopwatchWithCallback(fn, timeout); + }, timeout); + }; + + fn(NotificationSettings.MinTimeout); + + const currSeconds = $('.stopwatch-time').data('seconds'); + if (currSeconds) { + updateTimeInterval = updateStopwatchTime(currSeconds); + } +} + +async function updateStopwatchWithCallback(callback, timeout) { + const isSet = await updateStopwatch(); + + if (!isSet) { + timeout = NotificationSettings.MinTimeout; + } else if (timeout < NotificationSettings.MaxTimeout) { + timeout += NotificationSettings.TimeoutStep; + } + + callback(timeout); +} + +async function updateStopwatch() { + const data = await $.ajax({ + type: 'GET', + url: `${AppSubUrl}/api/v1/user/stopwatches`, + headers: {'X-Csrf-Token': csrf}, + }); + + if (updateTimeInterval) { + clearInterval(updateTimeInterval); + updateTimeInterval = null; + } + + const watch = data[0]; + const btnEl = $('.active-stopwatch-trigger'); + if (!watch) { + btnEl.addClass('hidden'); + } else { + const {repo_owner_name, repo_name, issue_index, seconds} = watch; + const issueUrl = `${AppSubUrl}/${repo_owner_name}/${repo_name}/issues/${issue_index}`; + $('.stopwatch-link').attr('href', issueUrl); + $('.stopwatch-commit').attr('action', `${issueUrl}/times/stopwatch/toggle`); + $('.stopwatch-cancel').attr('action', `${issueUrl}/times/stopwatch/cancel`); + $('.stopwatch-issue').text(`${repo_owner_name}/${repo_name}#${issue_index}`); + $('.stopwatch-time').text(prettyMilliseconds(seconds * 1000)); + updateStopwatchTime(seconds); + btnEl.removeClass('hidden'); + } + + return !!data.length; +} + +async function updateStopwatchTime(seconds) { + const secs = parseInt(seconds); + if (!Number.isFinite(secs)) return; + + const start = Date.now(); + updateTimeInterval = setInterval(() => { + const delta = Date.now() - start; + const dur = prettyMilliseconds(secs * 1000 + delta, {compact: true}); + $('.stopwatch-time').text(dur); + }, 1000); +} diff --git a/web_src/js/index.js b/web_src/js/index.js index 541f32507d..9a35507bab 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -22,6 +22,7 @@ import createDropzone from './features/dropzone.js'; import initTableSort from './features/tablesort.js'; import ActivityTopAuthors from './components/ActivityTopAuthors.vue'; import {initNotificationsTable, initNotificationCount} from './features/notification.js'; +import {initStopwatch} from './features/stopwatch.js'; import {createCodeEditor, createMonaco} from './features/codeeditor.js'; import {svg, svgs} from './svg.js'; import {stripTags} from './utils.js'; @@ -2626,6 +2627,7 @@ $(document).ready(async () => { initProject(), initServiceWorker(), initNotificationCount(), + initStopwatch(), renderMarkdownContent(), initGithook(), ]); |