enhance: refine repo watching (#38835)

Follow-up to https://github.com/go-gitea/gitea/pull/37571.

"Participating and mentions" deleted the watch row, so choosing it
dropped you out of the watcher count. It is a watch like the others, so
it now keeps a row and simply subscribes to no events.

The dashboard feed ignored the per-event options, so a "Custom: issues"
watcher still got pull request activity there. It now gates on the same
options as mail and notifications. That also closes a gap where pull
request reviews bypassed the permission check.

Also, address
https://github.com/go-gitea/gitea/pull/37571#discussion_r3740487363 and
reword a UI text for clarity.

---------

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
silverwind
2026-08-09 12:54:31 +02:00
committed by GitHub
parent 76a81b24f9
commit ad6107ab88
14 changed files with 137 additions and 92 deletions
+3 -1
View File
@@ -111,8 +111,10 @@ function onShowModalClick(el: HTMLElement, e: MouseEvent) {
if (attrTargetProp) {
assignElementProperty(attrTarget, attrTargetProp, attrib.value);
} else if (attrTarget.matches('input[type=checkbox], input[type=radio]')) {
(attrTarget as HTMLInputElement).checked = attrib.value === 'true';
} else if (attrTarget.matches('input, textarea')) {
(attrTarget as HTMLInputElement | HTMLTextAreaElement).value = attrib.value; // FIXME: add more supports like checkbox
(attrTarget as HTMLInputElement | HTMLTextAreaElement).value = attrib.value;
} else {
attrTarget.textContent = attrib.value; // FIXME: it should be more strict here, only handle div/span/p
}
+3 -18
View File
@@ -1,15 +1,10 @@
import {createTippy} from '../modules/tippy.ts';
import {showFomanticModal} from '../modules/fomantic/modal.ts';
import {registerGlobalEventFunc, registerGlobalInitFunc} from '../modules/observer.ts';
import type {Instance} from 'tippy.js';
let watchMenuTippy: Instance | null = null;
import {registerGlobalInitFunc} from '../modules/observer.ts';
export function initRepoWatch() {
registerGlobalInitFunc('initRepoWatchMenu', (btn: HTMLElement) => {
watchMenuTippy?.destroy(); // a watch action replaces the button, orphaning the old menu
const menu = btn.nextElementSibling!;
watchMenuTippy = createTippy(btn, {
const watchMenuTippy = createTippy(btn, {
content: menu,
theme: 'menu',
maxWidth: 350,
@@ -18,16 +13,6 @@ export function initRepoWatch() {
interactive: true,
hideOnClick: true,
});
menu.addEventListener('click', () => watchMenuTippy!.hide());
});
registerGlobalEventFunc('click', 'onRepoWatchOptionsClick', (btn: HTMLElement) => {
const elModal = document.querySelector<HTMLElement>('#repo-watch-options-modal')!;
const form = elModal.querySelector<HTMLFormElement>('form')!;
form.action = btn.getAttribute('data-url')!;
for (const el of form.querySelectorAll<HTMLInputElement>('input[type=checkbox]')) {
el.checked = btn.getAttribute(`data-${el.name.replaceAll('_', '-')}`) === 'true';
}
showFomanticModal(elModal);
menu.addEventListener('click', () => watchMenuTippy.hide());
});
}