From 7dfac7ba5fd0ba5f0d66135b6dde01c0501165f7 Mon Sep 17 00:00:00 2001 From: Chaphasilor Date: Sun, 27 Oct 2024 19:37:37 +0100 Subject: [PATCH] accessibility improvements --- .../AlbumScreen/track_list_tile.dart | 26 +++++++++++++---- lib/components/PlayerScreen/queue_list.dart | 21 +++++++++----- lib/l10n/app_en.arb | 28 +++++++++++++------ 3 files changed, 54 insertions(+), 21 deletions(-) diff --git a/lib/components/AlbumScreen/track_list_tile.dart b/lib/components/AlbumScreen/track_list_tile.dart index e466961f..c89a38ad 100644 --- a/lib/components/AlbumScreen/track_list_tile.dart +++ b/lib/components/AlbumScreen/track_list_tile.dart @@ -660,6 +660,15 @@ class TrackListItemTile extends StatelessWidget { Widget build(BuildContext context) { final bool secondRowNeeded = showArtists || showAlbum || showPlayCount; + final durationLabelFullHours = + (baseItem.runTimeTicksDuration()?.inHours ?? 0); + final durationLabelFullMinutes = + (baseItem.runTimeTicksDuration()?.inMinutes ?? 0) % 60; + final durationLabelSeconds = + (baseItem.runTimeTicksDuration()?.inSeconds ?? 0) % 60; + final durationLabelString = + "${durationLabelFullHours > 0 ? "$durationLabelFullHours ${AppLocalizations.of(context)!.hours} " : ""}${durationLabelFullMinutes > 0 ? "$durationLabelFullMinutes ${AppLocalizations.of(context)!.minutes} " : ""}$durationLabelSeconds ${AppLocalizations.of(context)!.seconds}"; + return ListTileTheme( tileColor: Theme.of(context).colorScheme.surfaceContainer, child: ListTile( @@ -829,17 +838,22 @@ class TrackListItemTile extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( - "${baseItem.runTimeTicksDuration()?.inMinutes.toString()}:${((baseItem.runTimeTicksDuration()?.inSeconds ?? 0) % 60).toString().padLeft(2, '0')}", + printDuration(baseItem.runTimeTicksDuration(), + leadingZeroes: false), + semanticsLabel: durationLabelString, textAlign: TextAlign.end, style: TextStyle( color: Theme.of(context).textTheme.bodySmall?.color, ), ), - AddToPlaylistButton( - item: baseItem, - size: 24, - visualDensity: const VisualDensity( - horizontal: -4, + Semantics( + excludeSemantics: true, + child: AddToPlaylistButton( + item: baseItem, + size: 24, + visualDensity: const VisualDensity( + horizontal: -4, + ), ), ), if (allowReorder) diff --git a/lib/components/PlayerScreen/queue_list.dart b/lib/components/PlayerScreen/queue_list.dart index b94b0379..5cba97e3 100644 --- a/lib/components/PlayerScreen/queue_list.dart +++ b/lib/components/PlayerScreen/queue_list.dart @@ -5,6 +5,7 @@ import 'package:finamp/components/AlbumScreen/track_list_tile.dart'; import 'package:finamp/components/AlbumScreen/song_menu.dart'; import 'package:finamp/components/Buttons/simple_button.dart'; import 'package:finamp/components/AddToPlaylistScreen/add_to_playlist_button.dart'; +import 'package:finamp/components/print_duration.dart'; import 'package:finamp/main.dart'; import 'package:finamp/models/finamp_models.dart'; import 'package:finamp/screens/blurred_player_screen_background.dart'; @@ -1054,17 +1055,23 @@ class QueueSectionHeader extends StatelessWidget { builder: (context, snapshot) { if (snapshot.hasData) { var remaining = snapshot.data!.remainingDuration; - var remainText = AppLocalizations.of(context)! - .remainingDuration( - remaining.inHours.toString(), - (remaining.inMinutes % 60) - .toString() - .padLeft(2, '0')); + var remainText = printDuration(remaining, + leadingZeroes: false); + final remainingLabelFullHours = + (remaining.inHours); + final remainingLabelFullMinutes = + (remaining.inMinutes) % 60; + final remainingLabelSeconds = + (remaining.inSeconds) % 60; + final remainingLabelString = + "${remainingLabelFullHours > 0 ? "$remainingLabelFullHours ${AppLocalizations.of(context)!.hours} " : ""}${remainingLabelFullMinutes > 0 ? "$remainingLabelFullMinutes ${AppLocalizations.of(context)!.minutes} " : ""}$remainingLabelSeconds ${AppLocalizations.of(context)!.seconds}"; return Padding( padding: const EdgeInsets.only( top: 4.0, right: 8.0), child: Text( - "${snapshot.data!.currentTrackIndex} / ${snapshot.data!.trackCount} ($remainText)")); + "${snapshot.data!.currentTrackIndex} / ${snapshot.data!.trackCount} (${AppLocalizations.of(context)!.remainingDuration(remainText)})", + semanticsLabel: + "${AppLocalizations.of(context)!.trackCountTooltip(snapshot.data!.currentTrackIndex, snapshot.data!.trackCount)} (${AppLocalizations.of(context)!.remainingDuration(remainingLabelString)})")); } return const SizedBox.shrink(); }), diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 5c23ee21..993c895b 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -635,6 +635,20 @@ "@timeFractionTooltip": { "description": "Tooltip and accessibility label for the track progress. {currentTime} is the current position within the track, as a translated string like '2 minutes 40 seconds', and {totalTime} is the total duration of the track, also a translated string." }, + "trackCountTooltip": "Track {currentTrackIndex} of {totalTrackCount}", + "@trackCountTooltip": { + "description": "Tooltip and accessibility label for the queue progress. {currentTrackIndex} and {totalTrackCount} are both numbers", + "placeholders": { + "currentTrackIndex": { + "type": "int", + "example": "10" + }, + "totalTrackCount": { + "type": "int", + "example": "13" + } + } + }, "invalidNumber": "Invalid Number", "@invalidNumber": {}, "sleepTimerTooltip": "Sleep timer", @@ -1552,17 +1566,15 @@ } } }, - "remainingDuration": "{hoursRemaining, select, 0{} other{{hoursRemaining}h }}{minutesRemaining}m remaining", + "remainingDuration": "{duration} remaining", "@remainingDuration": { + "description": "Displays duration of unplayed tracks. {duration} is a pre-formatted string.", "placeholders": { - "hoursRemaining": { - "type": "String" - }, - "minutesRemaining": { - "type": "String" + "duration": { + "type": "String", + "example": "36:23" } - }, - "description": "Displays duration of unplayed tracks" + } }, "removeFromPlaylistConfirm": "Remove", "removeFromPlaylistCancel": "Cancel",