implemented comprehensive accessibility (A11y) support across the app

This commit is contained in:
2026-07-13 23:41:47 +02:00
parent 8274dd46cd
commit 478f0ff20b
46 changed files with 590 additions and 226 deletions
+27 -7
View File
@@ -10,6 +10,7 @@ import 'package:http/http.dart' as http;
import '../model/account_data.dart';
import '../model/endpoint_data.dart';
import '../push/push_avatar.dart';
import 'a11y/a11y_labels.dart';
import 'avatar_disk_cache.dart';
class UserAvatar extends StatefulWidget {
@@ -17,6 +18,10 @@ class UserAvatar extends StatefulWidget {
final bool isGroup;
final int size;
/// Screenreader-Beschreibung. Aufrufer, die den Namen kennen, sollten ihn
/// mitgeben; sonst greift ein generisches „Profilbild"/„Gruppenbild".
final String? semanticLabel;
/// Server-side pixel size requested for user avatars. `null` lets the
/// widget pick `(size * 4).clamp(64, 1024)` — enough headroom for typical
/// device pixel ratios. Group avatars ignore this (Spreed serves one
@@ -28,6 +33,7 @@ class UserAvatar extends StatefulWidget {
this.isGroup = false,
this.size = 20,
this.requestSize,
this.semanticLabel,
super.key,
});
@@ -225,7 +231,9 @@ class _UserAvatarState extends State<UserAvatar> {
final pending = _pendingAvatars.putIfAbsent(url, () {
final future = _fetch(url);
future.whenComplete(() {
if (identical(_pendingAvatars[url], future)) _pendingAvatars.remove(url);
if (identical(_pendingAvatars[url], future)) {
_pendingAvatars.remove(url);
}
});
return future;
});
@@ -345,12 +353,24 @@ class _UserAvatarState extends State<UserAvatar> {
);
}
return CircleAvatar(
radius: radius,
backgroundColor: theme.primaryColor,
foregroundColor: Colors.white,
child: ClipOval(
child: SizedBox(width: radius * 2, height: radius * 2, child: content),
return Semantics(
image: true,
label:
widget.semanticLabel ??
(widget.isGroup
? A11yLabels.groupPicture
: A11yLabels.profilePicture),
child: CircleAvatar(
radius: radius,
backgroundColor: theme.primaryColor,
foregroundColor: Colors.white,
child: ClipOval(
child: SizedBox(
width: radius * 2,
height: radius * 2,
child: content,
),
),
),
);
}