Profilbilder: Avatar-Upload, Anzeige auf Profil & Feed

- user.avatar-Spalte (Schema, migrate.sh, Migrationsdoku)
- POST /user/avatar (geschützt): Upload via storeImage, ersetzt/löscht altes Bild
- avatar in /u/{name}/info, /user/info und im entrySelect-Join (Feed-Karten)
- Account-Löschung entfernt auch das Avatar-File
- Frontend: Avatar im Profilkopf + Byline der Karten (50px), Upload-Form,
  Platzhalterbild no_profile_pic.jpg als Fallback
- .card img per :not(.avatar) von Beitragsbildern getrennt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 18:20:14 +02:00
parent cad1fa5c5c
commit 15ef7db5f7
11 changed files with 153 additions and 20 deletions
+11 -6
View File
@@ -57,7 +57,8 @@ CREATE TABLE user (
username TEXT UNIQUE,
password BLOB,
created_at INTEGER,
last_login INTEGER
last_login INTEGER,
avatar TEXT NOT NULL DEFAULT ''
);
CREATE TABLE session (
id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -91,14 +92,18 @@ SCHEMA
# Prüfen, welche optionalen Spalten in der Quelle vorhanden sind.
# Ältere Python-DBs haben reply_count und last_activity noch nicht.
has_col() {
sqlite3 "$SRC" "SELECT COUNT(*) FROM pragma_table_info('entry') WHERE name='$1';"
sqlite3 "$SRC" "SELECT COUNT(*) FROM pragma_table_info('$1') WHERE name='$2';"
}
reply_count_expr="0"
[[ "$(has_col reply_count)" == "1" ]] && reply_count_expr="COALESCE(e.reply_count, 0)"
[[ "$(has_col entry reply_count)" == "1" ]] && reply_count_expr="COALESCE(e.reply_count, 0)"
last_activity_expr="e.created_at"
[[ "$(has_col last_activity)" == "1" ]] && last_activity_expr="COALESCE(e.last_activity, e.created_at)"
[[ "$(has_col entry last_activity)" == "1" ]] && last_activity_expr="COALESCE(e.last_activity, e.created_at)"
# Profilbild: alte DBs haben die Spalte nicht -> leerer String.
avatar_expr="''"
[[ "$(has_col user avatar)" == "1" ]] && avatar_expr="COALESCE(u.avatar, '')"
replies_filter=""
[[ "$REPLIES" == "drop" ]] && replies_filter="AND e.reply_to = 0"
@@ -114,8 +119,8 @@ ATTACH '$src_sql' AS src;
BEGIN;
-- User übernehmen; nur Spalten des aktuellen Schemas (Quelle kann Extra-Spalten haben)
INSERT INTO user (id, uid, username, password, created_at, last_login)
SELECT id, uid, username, password, created_at, last_login FROM src.user;
INSERT INTO user (id, uid, username, password, created_at, last_login, avatar)
SELECT u.id, u.uid, u.username, u.password, u.created_at, u.last_login, $avatar_expr FROM src.user u;
-- Einträge transformieren:
-- filepath NULL und 'none' -> '' (Go-Zero-Value; scanEntries erwartet string, nicht *string)