Repository: WeblateOrg/weblate

Issue:
Orphan screenshot warning doesn't disappear after clear all of unused screenshots
### Describe the issue

Hello!

Recently I found that WebLate doesn't get rid of the "Here is at least one unused screenshot presented" warning after I removed all screenshots that has no assigned string. They appeared because of the recent project-side rework that caused removal of a pile of strings that got been replaced with another one. And once I got that warning, I started to remove these screenshots (as they are now obsolete on my side). However, the warning still not gone after one day since I removed all unused screnshots. And, additionally, there is totally no way to remove it manually...

### I already tried

- [X] I've read and searched [the documentation](https://docs.weblate.org/).
- [X] I've searched for similar filed issues in this repository.

### Steps to reproduce the behavior

1. Have a pile of strings.
2. Upload a screenshot for each of them.
3. On the project side, remove some number of strings, and add another one.
4. Wait when "Unused screenshots" warning will pops up.
5. Open screenshots list and remove every screenshot marked by red exclamation sign.
6. Wait again, and...
7. It still appears. I checked trice the whole list of screenshots on all 7 pages (on my end), I swear I removed every unused screenshot, and warning still wasn't gone.

### Expected behavior

The warning gets disappear after all unused screenshots got been removed or assigned to anything also.

### Screenshots

![Снимок экрана от 2024-03-05 21-04-08](https://github.com/WeblateOrg/weblate/assets/6751442/bbd36054-e0d2-4bfe-86f9-c9a2b9b58c06)


### Exception traceback

_No response_

### How do you run Weblate?

weblate.org service

### Weblate versions

_No response_

### Weblate deploy checks

_No response_

### Additional context

The project and its component where the problem ocurred: https://hosted.weblate.org/projects/thextech/engine-general/


Discussion:
It indeed might take some time to update, but it should be possible to make it immediate.
This issue seems to be a good fit for newbie contributors. You are welcome to contribute to Weblate! Don't hesitate to ask any questions you would have while implementing this.

You can learn about how to get started in our [contributors documentation](https://docs.weblate.org/en/latest/contributing/index.html).
> It indeed might take some time to update, but it should be possible to make it immediate.

Absolutely no hurry, do as you can. :)

> newbie contributors

This bot seems doesn't know that I contributed some tweaks on the Qt translation files support a while ago, and I had already reported some issues (or asked questions) during the history. xD
To immediately clear the alert, a m2m_change signal on `Screenshot.units` should trigger `component.update_alerts` method.

Resolving patch:
diff --git a/weblate/screenshots/models.py b/weblate/screenshots/models.py
--- a/weblate/screenshots/models.py
+++ b/weblate/screenshots/models.py
@@ -14,7 +14,7 @@
 from django.core.files.storage import default_storage
 from django.db import models
 from django.db.models import Q
-from django.db.models.signals import m2m_changed
+from django.db.models.signals import m2m_changed, post_delete
 from django.dispatch import receiver
 from django.urls import reverse
 from django.utils.translation import gettext_lazy
@@ -24,8 +24,8 @@
 from weblate.screenshots.fields import ScreenshotField
 from weblate.trans.mixins import UserDisplayMixin
 from weblate.trans.models import Translation, Unit
+from weblate.trans.models.alert import update_alerts
 from weblate.trans.signals import vcs_post_update
-from weblate.trans.tasks import component_alerts
 from weblate.utils.decorators import disable_for_loaddata
 from weblate.utils.errors import report_error
 from weblate.utils.validators import validate_bitmap
@@ -105,7 +105,16 @@ def change_screenshot_assignment(sender, instance, action, **kwargs):
     if instance.translation.component.alert_set.filter(
         name="UnusedScreenshot"
     ).exists():
-        component_alerts.delay([instance.pk])
+        update_alerts(instance.translation.component, alerts={"UnusedScreenshot"})
+
+
+@receiver(post_delete, sender=Screenshot)
+def update_alerts_on_screenshot_delete(sender, instance, **kwargs):
+    # Update the unused screenshot alert if screenshot is deleted
+    if instance.translation.component.alert_set.filter(
+        name="UnusedScreenshot"
+    ).exists():
+        update_alerts(instance.translation.component, alerts={"UnusedScreenshot"})
 
 
 def validate_screenshot_image(component, filename):


Test patch: