feat: improve mobile screen reader accessibility (#17876)

* WIP: adding screen reader support to mobile

* implemented getAltText

* implemented alt text solution that stores the alt text in the DB, which isn't really great

* moved alt text computation to immich_thumbnail.dart

* added unit tests

* revert unintended changes

* Added text to remaining buttons in Photo page

* fixed import

* Fixed issue of easy_localization not parsing select blocks

* Transferred the new screen reader help to web frontend

* remove unused property

* npm run format:fix

* code review

* revert unwanted change

* dart fmt

* revert web changes

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
Andreas Tollkötter 2025-06-13 16:39:59 +02:00 committed by GitHub
parent ed5b260eeb
commit f54cfa7a5a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 170 additions and 15 deletions

View file

@ -6,6 +6,7 @@ import 'package:immich_mobile/providers/image/immich_local_thumbnail_provider.da
import 'package:immich_mobile/providers/image/immich_remote_thumbnail_provider.dart';
import 'package:immich_mobile/entities/asset.entity.dart';
import 'package:immich_mobile/utils/hooks/blurhash_hook.dart';
import 'package:immich_mobile/utils/thumbnail_utils.dart';
import 'package:immich_mobile/widgets/common/immich_image.dart';
import 'package:immich_mobile/widgets/common/thumbhash_placeholder.dart';
import 'package:octo_image/octo_image.dart';
@ -77,6 +78,13 @@ class ImmichThumbnail extends HookConsumerWidget {
);
}
final assetAltText = getAltText(
asset!.exifInfo,
asset!.fileCreatedAt,
asset!.type,
[],
);
final thumbnailProviderInstance = ImmichThumbnail.imageProvider(
asset: asset,
userId: userId,
@ -90,18 +98,21 @@ class ImmichThumbnail extends HookConsumerWidget {
return originalErrorWidgetBuilder(ctx, error, stackTrace);
}
return OctoImage.fromSet(
placeholderFadeInDuration: Duration.zero,
fadeInDuration: Duration.zero,
fadeOutDuration: const Duration(milliseconds: 100),
octoSet: OctoSet(
placeholderBuilder: blurHashPlaceholderBuilder(blurhash, fit: fit),
errorBuilder: customErrorBuilder,
return Semantics(
label: assetAltText,
child: OctoImage.fromSet(
placeholderFadeInDuration: Duration.zero,
fadeInDuration: Duration.zero,
fadeOutDuration: const Duration(milliseconds: 100),
octoSet: OctoSet(
placeholderBuilder: blurHashPlaceholderBuilder(blurhash, fit: fit),
errorBuilder: customErrorBuilder,
),
image: thumbnailProviderInstance,
width: width,
height: height,
fit: fit,
),
image: thumbnailProviderInstance,
width: width,
height: height,
fit: fit,
);
}
}