import uuid from django.conf import settings from django.db import models class Bookmark(models.Model): """A saved passage anchor in an uploaded ebook (EPUB CFI + optional thought).""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="bookmarks", db_index=True, ) ebook = models.ForeignKey( "books.EBook", on_delete=models.CASCADE, related_name="bookmarks", db_index=True, ) epub_cfi = models.CharField(max_length=2048, db_index=True) chapter_index = models.PositiveIntegerField(default=0, db_index=True) chapter_title = models.CharField(max_length=512, blank=True, default="") page = models.PositiveIntegerField( default=1, help_text="Legacy/display page; derived from chapter_index + 1", ) location_text = models.TextField( blank=True, default="", help_text="The selected passage text at this location", ) content = models.TextField( blank=True, default="", help_text="Optional user thought; empty means bookmark-only", ) highlight_color = models.CharField( max_length=7, default="#fde047", help_text="Hex color for in-book passage highlight (e.g. #fde047)", ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = "annotations_bookmark" verbose_name = "Bookmark" verbose_name_plural = "Bookmarks" ordering = ["chapter_index", "epub_cfi"] constraints = [ models.UniqueConstraint( fields=["user", "ebook", "epub_cfi"], name="uq_bookmark_user_ebook_cfi", ) ] def __str__(self) -> str: return f"{self.user} @ {self.ebook} ch.{self.chapter_index}" class Note(models.Model): """Legacy note model; new UX uses Bookmark.content instead.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="notes", db_index=True, ) book = models.ForeignKey( "books.Book", on_delete=models.CASCADE, related_name="notes", db_index=True, ) page = models.PositiveIntegerField() location_text = models.TextField( blank=True, default="", help_text="The selected passage text this note refers to", ) content = models.TextField( help_text="The note body content" ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = "annotations_note" verbose_name = "Note" verbose_name_plural = "Notes" ordering = ["-created_at"] def __str__(self) -> str: preview = self.content[:50] return f"{self.user} @ {self.book} p.{self.page}: {preview}"