fix & feat: resolve user reports #1 through #8 (TTS voice & speed, modals, scrollbar, CEFR hint, SRS grammar exclusion, global word lookup)

This commit is contained in:
Antigravity committed 2026-10-08 12:37:41 +03:00
1 parent 8cffae46fa
commit 7871191c90
12 files changed
+443 -103

No files matched your search

+9 -3
View File
@@ -12,7 +12,8 @@ logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/feedback", tags=["Feedback & Bug Tracker"])
# Path to workspace memory file for seamless Antigravity AI reading
# Paths to markdown reports files for seamless Antigravity AI reading
DATA_REPORTS_FILE = Path(__file__).resolve().parent.parent.parent / "data" / "USER_REPORTS.md"
MEMORY_REPORTS_FILE = Path("/home/ai-projects/memory/USER_REPORTS.md")
@@ -97,8 +98,13 @@ def sync_reports_to_markdown(conn):
lines.append(f"- [x] **#{r['id']} {cat_emoji} ({r['created_at']})**: {r['message'].strip()} *(Страница: {r['context_url'] or 'общая'})*")
lines.append("")
MEMORY_REPORTS_FILE.parent.mkdir(parents=True, exist_ok=True)
MEMORY_REPORTS_FILE.write_text("\n".join(lines), encoding="utf-8")
content = "\n".join(lines)
for target in [DATA_REPORTS_FILE, MEMORY_REPORTS_FILE]:
try:
target.parent.mkdir(parents=True, exist_ok=True)
target.write_text(content, encoding="utf-8")
except Exception as e:
logger.debug(f"Could not write to {target}: {e}")
except Exception as e:
logger.warning(f"Could not sync reports to markdown: {e}")
+18 -2
View File
@@ -24,6 +24,7 @@ async def api_srs_queue(
tag: Optional[str] = None,
limit: int = 25,
mix: bool = False,
exclude_grammar: bool = True,
user: dict = Depends(require_user),
):
"""
@@ -46,6 +47,13 @@ async def api_srs_queue(
col_filter += " AND tags LIKE ?"
col_params.append(f"%{tag.strip()}%")
# Exclude grammar cards from standard SRS vocabulary training unless grammar collection/tag is specifically requested
wants_grammar = (collection and ("грамматика" in collection.lower() or "grammar" in collection.lower())) or \
(tag and "grammar" in tag.lower())
if exclude_grammar and not wants_grammar:
col_filter += " AND (collection IS NULL OR (collection != 'Грамматика Мерфи' AND collection NOT LIKE '%grammar%'))"
col_filter += " AND (tags IS NULL OR tags NOT LIKE '%grammar%')"
if mix:
# 1. New cards (up to 10)
new_rows = conn.execute(
@@ -117,6 +125,7 @@ async def api_srs_quiz(
collection: Optional[str] = None,
tag: Optional[str] = None,
count: int = 10,
exclude_grammar: bool = True,
user: dict = Depends(require_user),
):
"""
@@ -132,15 +141,22 @@ async def api_srs_quiz(
col_filter += " AND tags LIKE ?"
col_params.append(f"%{tag.strip()}%")
wants_grammar = (collection and ("грамматика" in collection.lower() or "grammar" in collection.lower())) or \
(tag and "grammar" in tag.lower())
if exclude_grammar and not wants_grammar:
col_filter += " AND (collection IS NULL OR (collection != 'Грамматика Мерфи' AND collection NOT LIKE '%grammar%'))"
col_filter += " AND (tags IS NULL OR tags NOT LIKE '%grammar%')"
rows = conn.execute(
f"SELECT * FROM vocabulary_cards WHERE user_id = ?{col_filter} ORDER BY RANDOM() LIMIT ?",
[user["id"]] + col_params + [count],
).fetchall()
target_cards = [dict(r) for r in rows]
# Fetch pool of all user cards for generating smart distractors
# Fetch pool of user cards for generating smart distractors (exclude grammar)
distractor_filter = " AND (collection IS NULL OR (collection != 'Грамматика Мерфи' AND collection NOT LIKE '%grammar%')) AND (tags IS NULL OR tags NOT LIKE '%grammar%')" if exclude_grammar and not wants_grammar else ""
all_rows = conn.execute(
"SELECT id, term, translation, part_of_speech FROM vocabulary_cards WHERE user_id = ?",
f"SELECT id, term, translation, part_of_speech FROM vocabulary_cards WHERE user_id = ?{distractor_filter}",
(user["id"],),
).fetchall()
all_cards = [dict(r) for r in all_rows]