mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-04 14:54:14 +00:00
516a4883fa
Clean up the navbar template and styling, and fix the navbar stopwatch, which navigated to the issue instead of opening its popup since https://github.com/go-gitea/gitea/pull/36965. 1. Add hover background to the create and user menus 2. Simplify navbar HTML and CSS and remove Fomantic styles 3. Render the notification and stopwatch icons once instead of separate mobile and desktop copies 4. Make the stopwatch a keyboard accessible button whose popup updates on push and closes when the stopwatch stops Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: bircni <bircni@icloud.com>
87 lines
3.3 KiB
TypeScript
87 lines
3.3 KiB
TypeScript
import {createTippy} from '../modules/tippy.ts';
|
|
import {GET} from '../modules/fetch.ts';
|
|
import {hideElem, showElem} from '../utils/dom.ts';
|
|
import {onUserEvent} from '../modules/worker.ts';
|
|
import type {StopwatchData} from '../types.ts';
|
|
import {registerGlobalInitFunc} from '../modules/observer.ts';
|
|
|
|
const {appSubUrl, notificationSettings} = window.config;
|
|
|
|
export const initStopwatch = () => registerGlobalInitFunc('initActiveStopwatchNotification', (btn: HTMLElement) => {
|
|
// Init the icon + popup even when no stopwatch is active so a real-time push has a target to toggle.
|
|
const popup = btn.nextElementSibling!;
|
|
const tippy = createTippy(btn, {
|
|
content: popup,
|
|
placement: 'bottom-end',
|
|
trigger: 'click',
|
|
maxWidth: 'none',
|
|
interactive: true,
|
|
hideOnClick: true,
|
|
theme: 'default',
|
|
});
|
|
|
|
// TODO: This flickers on page load, we could avoid this by making a custom element to render time periods.
|
|
const updateStopwatchTime = (seconds: number) => {
|
|
const hours = seconds / 3600 || 0;
|
|
const minutes = seconds / 60 || 0;
|
|
btn.querySelector('.header-stopwatch-dot')!.textContent = hours >= 1 ? `${Math.round(hours)}h` : `${Math.round(minutes)}m`;
|
|
};
|
|
|
|
const updateStopwatchData = (data: Array<StopwatchData>) => {
|
|
const watch = data[0];
|
|
if (!watch) {
|
|
tippy.hide();
|
|
hideElem(btn);
|
|
return false;
|
|
}
|
|
const {repo_owner_name, repo_name, issue_index, seconds} = watch;
|
|
const issueUrl = `${appSubUrl}/${repo_owner_name}/${repo_name}/issues/${issue_index}`;
|
|
popup.querySelector('.stopwatch-link')!.setAttribute('href', issueUrl);
|
|
popup.querySelector('.stopwatch-commit')!.setAttribute('action', `${issueUrl}/times/stopwatch/stop`);
|
|
popup.querySelector('.stopwatch-cancel')!.setAttribute('action', `${issueUrl}/times/stopwatch/cancel`);
|
|
popup.querySelector('.stopwatch-issue')!.textContent = `${repo_owner_name}/${repo_name}#${issue_index}`;
|
|
updateStopwatchTime(seconds);
|
|
showElem(btn);
|
|
return true;
|
|
};
|
|
|
|
const updateStopwatch = async () => {
|
|
try {
|
|
const response = await GET(`${appSubUrl}/user/stopwatches`);
|
|
if (!response.ok) {
|
|
console.error('Failed to fetch stopwatch data');
|
|
return false;
|
|
}
|
|
return updateStopwatchData(await response.json());
|
|
} catch (error) {
|
|
console.error(error);
|
|
return false;
|
|
}
|
|
};
|
|
|
|
const startPeriodicPoller = (timeout: number) => {
|
|
if (timeout <= 0 || !Number.isFinite(timeout)) return;
|
|
setTimeout(async () => {
|
|
if (!await updateStopwatch()) {
|
|
timeout = notificationSettings.MinTimeout;
|
|
} else if (timeout < notificationSettings.MaxTimeout) {
|
|
timeout += notificationSettings.TimeoutStep;
|
|
}
|
|
startPeriodicPoller(timeout);
|
|
}, timeout);
|
|
};
|
|
|
|
const seconds = btn.getAttribute('data-seconds');
|
|
if (seconds) updateStopwatchTime(parseInt(seconds));
|
|
|
|
let pollerStarted = false;
|
|
onUserEvent('stopwatches', (msg) => updateStopwatchData(msg.eventData));
|
|
// On each (re)connect, reconcile stopwatch state from the server to recover any push dropped during the connect gap.
|
|
onUserEvent('worker-connected', () => { updateStopwatch() }); // no await
|
|
onUserEvent('worker-unavailable', () => {
|
|
if (pollerStarted) return;
|
|
pollerStarted = true;
|
|
startPeriodicPoller(notificationSettings.MinTimeout);
|
|
});
|
|
});
|