docs: add block/mute user relations, emoji-sync CLI, and uid indexes

- Add `/block`, `/mute` endpoints with block/unblock and mute/unmute functionality in `routers/relations.py`, hiding blocked users' content everywhere except their own profile while muting only suppresses notifications
- Introduce `devplace emoji-sync` CLI command to regenerate `static/js/emoji-shortcodes.js` from the emoji library, documented in `CLAUDE.md` and wired in `cli.py`
- Create `get_blocked_uids()` database helper and apply it in `content.py` `load_detail()` to filter blocked users' posts from detail views
- Implement `_uid_index()` and `_drop_index()` helpers in `database.py` for unique uid indexes across tables, with `user_relations` added to `SOFT_DELETE_TABLES`
- Document new routes in `AGENTS.md` and `README.md`, including emoji shortcodes rendering behavior distinct from the emoji picker
This commit is contained in:
2026-06-19 08:06:09 +00:00
parent f3a4667fce
commit 741d7aade6
136 changed files with 3025 additions and 564 deletions
+4 -4
View File
@@ -72,7 +72,7 @@
{% endif %}
{% set _type = "project" %}{% set _uid = project['uid'] %}{% set _bookmarked = bookmarked %}{% include "_bookmark_button.html" %}
{% set _type = "project" %}{% set _uid = project['uid'] %}{% set _reactions = reactions %}{% include "_reaction_bar.html" %}
<button type="button" class="project-star-btn project-actions-more" aria-haspopup="menu" aria-label="More actions"><span class="icon">&#x22EF;</span><span class="label"> More</span></button>
<button type="button" class="project-star-btn project-actions-more" aria-haspopup="menu" aria-expanded="false" aria-label="More actions"><span class="icon">&#x22EF;</span><span class="label"> More</span></button>
<div class="project-actions-overflow" hidden>
{% if is_admin(user) %}
@@ -128,7 +128,7 @@
<div class="auth-field auth-field-gap">
<label>Type</label>
<div class="flex-wrap-gap">
<div class="flex-wrap-gap" role="group" aria-label="Type">
{% for t in [('game', 'Game'), ('game_asset', 'Game Asset'), ('software', 'Software'), ('mobile_app', 'Mobile App'), ('website', 'Website')] %}
<label class="topic-label">
<input type="radio" name="project_type" value="{{ t[0] }}" {% if t[0] == project.get('project_type', 'software') %}checked{% endif %} class="topic-radio">
@@ -140,7 +140,7 @@
<div class="auth-field auth-field-gap">
<label>Status</label>
<div class="flex-wrap-gap">
<div class="flex-wrap-gap" role="group" aria-label="Status">
<label class="topic-label">
<input type="radio" name="status" value="In Development" {% if project.get('status', 'In Development') != 'Released' %}checked{% endif %} class="topic-radio"> In Development
</label>
@@ -153,7 +153,7 @@
<div class="auth-field auth-field-gap-last">
<label>Platforms</label>
<div id="platforms-tags" class="flex-wrap-gap-bottom"></div>
<input type="text" id="platforms-input" class="input-sm" placeholder="Add platform (press Enter)">
<input type="text" id="platforms-input" class="input-sm" placeholder="Add platform (press Enter)" aria-label="Add platform">
<input type="hidden" id="platforms" name="platforms" value="{{ project.get('platforms', '') }}">
<div class="platform-presets-wrap">
{% for p in ['PC', 'Windows', 'Mac', 'Linux', 'iOS', 'Android', 'Web', 'Console'] %}