feat: integrate invite API and improve notification handling

- Add invite code display and binding functionality via API
- Fix notification unread count sync on auth state change
- Improve notification mark read with server state validation
- Add auth state listener to trigger notification refresh
- Add YaoCoinConverter for coin-to-yao type conversion
- Remove YaoLegend from divination screens (UI cleanup)
- Abbreviate relation labels in yao detail view
- Add re-register notice to account delete screen
- Update 'coins' terminology to 'points' in localization
- Fix backend points consumption to only run in CHAT mode
- Add HttpxAuthNoiseFilter to suppress auth endpoint logging
- Fix notification static_schema import path
- Add test coverage for notification bloc error handling
- Update AGENTS.md page header rules and image handling
- Delete deprecated run-dev.sh script
This commit is contained in:
qzl
2026-04-13 14:52:22 +08:00
parent da947f9f08
commit 1e22f27de2
52 changed files with 1419 additions and 307 deletions
@@ -3,6 +3,7 @@ from __future__ import annotations
from datetime import datetime
from uuid import UUID
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy import func, select, update
from sqlalchemy.ext.asyncio import AsyncSession
@@ -111,3 +112,37 @@ class NotificationRepository:
await self._session.execute(stmt)
await self._session.flush()
return count
async def commit(self) -> None:
await self._session.commit()
async def link_published_notifications_to_user(self, *, user_id: UUID) -> int:
notification_ids = list(
(
await self._session.execute(
select(Notification.id).where(
Notification.status == "published",
Notification.deleted_at.is_(None),
)
)
)
.scalars()
.all()
)
if not notification_ids:
return 0
stmt = (
insert(UserNotification)
.values(
[
{"user_id": user_id, "notification_id": notification_id}
for notification_id in notification_ids
]
)
.on_conflict_do_nothing(index_elements=["user_id", "notification_id"])
.returning(UserNotification.id)
)
result = await self._session.execute(stmt)
await self._session.flush()
return len(list(result.scalars().all()))