feat: Add Chat UX improvements with notifications and @mention support

- Add ActionBar component with expandable toolbar for mobile
- Add @mention functionality with autocomplete dropdown
- Add browser notification system (push, sound, vibration)
- Add NotificationSettings modal for user preferences
- Add mention badges on room list cards
- Add ReportPreview with Markdown rendering and copy/download
- Add message copy functionality with hover actions
- Add backend mentions field to messages with Alembic migration
- Add lots field to rooms, remove templates
- Optimize WebSocket database session handling
- Various UX polish (animations, accessibility)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
egg
2025-12-08 08:20:37 +08:00
parent 92834dbe0e
commit 599802b818
72 changed files with 6810 additions and 702 deletions

View File

@@ -61,6 +61,12 @@ class Settings(BaseSettings):
REPORT_MAX_MESSAGES: int = 200 # Summarize if exceeded
REPORT_STORAGE_PATH: str = "reports" # MinIO path prefix for reports
# Database Connection Pool
DB_POOL_SIZE: int = 20 # Number of persistent connections
DB_MAX_OVERFLOW: int = 30 # Max additional connections beyond pool_size
DB_POOL_TIMEOUT: int = 10 # Seconds to wait for available connection
DB_POOL_RECYCLE: int = 1800 # Recycle connections after 30 minutes
@field_validator("LOG_LEVEL")
@classmethod
def validate_log_level(cls, v: str) -> str:

View File

@@ -3,20 +3,23 @@
Supports MySQL database with connection pooling.
All tables use 'tr_' prefix to avoid conflicts in shared database.
"""
from contextlib import contextmanager
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import sessionmaker, Session
from app.core.config import get_settings
settings = get_settings()
# Create engine with MySQL connection pooling
# Pool settings are configurable via environment variables
engine = create_engine(
settings.DATABASE_URL,
pool_size=5,
max_overflow=10,
pool_size=settings.DB_POOL_SIZE,
max_overflow=settings.DB_MAX_OVERFLOW,
pool_timeout=settings.DB_POOL_TIMEOUT,
pool_pre_ping=True, # Verify connection before using
pool_recycle=3600, # Recycle connections after 1 hour
pool_recycle=settings.DB_POOL_RECYCLE,
echo=settings.DEBUG,
)
@@ -34,3 +37,21 @@ def get_db():
yield db
finally:
db.close()
@contextmanager
def get_db_context() -> Session:
"""Context manager for short-lived database sessions.
Use this for operations that need a database session but should
not hold onto it for the entire request/connection lifecycle.
Example:
with get_db_context() as db:
result = db.query(Model).filter(...).first()
"""
db = SessionLocal()
try:
yield db
finally:
db.close()