Private
Public Access
Text was too small on high-DPI screens with no in-app fix beyond browser zoom. Adds a text-size setting (scales the whole app via a root font-size percentage), auto-large rendering for emoji-only messages, and an independent emoji-size preference that also scales reaction pills without affecting the emoji picker's fixed-size grid. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
53 lines
2.8 KiB
Python
53 lines
2.8 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import Boolean, DateTime, ForeignKey, String, func
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.models.base import Base
|
|
|
|
|
|
class User(Base):
|
|
__tablename__ = "users"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4)
|
|
username: Mapped[str] = mapped_column(String(50), unique=True, index=True, nullable=False)
|
|
email: Mapped[str] = mapped_column(String(255), unique=True, index=True, nullable=False)
|
|
password_hash: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
is_bot: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
|
|
is_site_admin: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
|
|
is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
|
display_name: Mapped[str | None] = mapped_column(String(50))
|
|
theme: Mapped[str | None] = mapped_column(String(20))
|
|
# #71: null means "normal" (the pre-existing default before this
|
|
# setting existed) -- a preset name, not a raw scale factor, so it's
|
|
# validated/enumerable the same way `theme` already is rather than
|
|
# accepting an arbitrary float.
|
|
text_scale: Mapped[str | None] = mapped_column(String(20))
|
|
# #71: independent of text_scale above -- scales emoji rendered in
|
|
# message text specifically, not the whole UI (see
|
|
# frontend/src/components/MessageContent.tsx's --emoji-scale, scoped
|
|
# to message content only so it can't also inflate the emoji picker's
|
|
# grid or reaction pills).
|
|
emoji_scale: Mapped[str | None] = mapped_column(String(20))
|
|
# Only meaningful when theme == "custom" -- which of this user's saved
|
|
# CustomTheme rows (app/models/custom_theme.py) is currently active.
|
|
# Cleared explicitly (not via a DB-level ON DELETE) whenever that theme
|
|
# is deleted -- see custom_theme_service.delete_custom_theme, which also
|
|
# resets `theme` back to a preset in the same transaction so the two
|
|
# columns can't go out of sync.
|
|
active_custom_theme_id: Mapped[uuid.UUID | None] = mapped_column(
|
|
ForeignKey("custom_themes.id"), nullable=True
|
|
)
|
|
avatar_filename: Mapped[str | None] = mapped_column(String(64))
|
|
avatar_content_type: Mapped[str | None] = mapped_column(String(50))
|
|
# Manual override for the presence indicator -- when set, this user
|
|
# always shows as offline to everyone regardless of actual connection
|
|
# state (a "lurk" mode), independent of any individual room.
|
|
appear_offline: Mapped[bool] = mapped_column(Boolean, default=False, server_default="false", nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), nullable=False
|
|
)
|
|
|
|
active_custom_theme = relationship("CustomTheme", foreign_keys=[active_custom_theme_id])
|