Skip to content

Commit

Permalink
add proper translatable strings for accessibility labels
Browse files Browse the repository at this point in the history
  • Loading branch information
Chaphasilor committed Sep 24, 2024
1 parent d9db25a commit 6ecdb9d
Show file tree
Hide file tree
Showing 14 changed files with 479 additions and 406 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class _AddToPlaylistButtonState extends ConsumerState<AddToPlaylistButton> {
return Semantics.fromProperties(
properties: SemanticsProperties(
label: AppLocalizations.of(context)!.addToPlaylistTooltip,
hint: "Tap to add to playlist. Long press to toggle favorite.",
hint: AppLocalizations.of(context)!.playlistActionsMenuButtonTooltip,
button: true,
),
excludeSemantics: true,
Expand Down
55 changes: 24 additions & 31 deletions lib/components/AlbumScreen/download_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,37 +53,30 @@ class DownloadButton extends ConsumerWidget {
viewId = finampUserHelper.currentUser!.currentViewId!;
}

var downloadButton = Semantics.fromProperties(
properties: SemanticsProperties(
label: AppLocalizations.of(context)!.downloadItem,
button: true,
),
container: true,
child: IconButton(
icon: status == DownloadItemStatus.notNeeded
? const Icon(Icons.file_download)
: const Icon(Icons.lock), //TODO get better icon
onPressed: () async {
if (isLibrary) {
await showDialog(
context: context,
builder: (context) => ConfirmationPromptDialog(
promptText: AppLocalizations.of(context)!
.downloadLibraryPrompt(item.name),
confirmButtonText:
AppLocalizations.of(context)!.addButtonLabel,
abortButtonText:
MaterialLocalizations.of(context).cancelButtonLabel,
onConfirmed: () =>
DownloadDialog.show(context, item, viewId),
onAborted: () {},
));
} else {
await DownloadDialog.show(context, item, viewId);
}
},
tooltip: parentTooltip,
),
var downloadButton = IconButton(
icon: status == DownloadItemStatus.notNeeded
? const Icon(Icons.file_download)
: const Icon(Icons.lock), //TODO get better icon
onPressed: () async {
if (isLibrary) {
await showDialog(
context: context,
builder: (context) => ConfirmationPromptDialog(
promptText: AppLocalizations.of(context)!
.downloadLibraryPrompt(item.name),
confirmButtonText:
AppLocalizations.of(context)!.addButtonLabel,
abortButtonText:
MaterialLocalizations.of(context).cancelButtonLabel,
onConfirmed: () =>
DownloadDialog.show(context, item, viewId),
onAborted: () {},
));
} else {
await DownloadDialog.show(context, item, viewId);
}
},
tooltip: parentTooltip,
);
var deleteButton = IconButton(
icon: const Icon(Icons.delete),
Expand Down
2 changes: 1 addition & 1 deletion lib/components/PlayerScreen/album_chip.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class _AlbumChipContent extends StatelessWidget {

return Semantics.fromProperties(
properties: SemanticsProperties(
label: "$albumName (Album)",
label: "$albumName (${AppLocalizations.of(context)!.album})",
button: true,
),
excludeSemantics: true,
Expand Down
2 changes: 1 addition & 1 deletion lib/components/PlayerScreen/artist_chip.dart
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ class _ArtistChipContent extends StatelessWidget {

return Semantics.fromProperties(
properties: SemanticsProperties(
label: "$name (Artist)",
label: "$name (${AppLocalizations.of(context)!.artist})",
button: true,
),
container: true,
Expand Down
13 changes: 7 additions & 6 deletions lib/components/PlayerScreen/player_buttons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:flutter/semantics.dart';
import 'package:flutter_tabler_icons/flutter_tabler_icons.dart';
import 'package:flutter_vibrate/flutter_vibrate.dart';
import 'package:get_it/get_it.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import '../../services/media_state_stream.dart';
import '../../services/music_player_background_task.dart';
Expand Down Expand Up @@ -34,8 +35,8 @@ class PlayerButtons extends StatelessWidget {
if (controller.shouldShow(PlayerHideable.loopShuffleButtons))
PlayerButtonsRepeating(),
Semantics.fromProperties(
properties: const SemanticsProperties(
label: "Skip to beginning or previous track",
properties: SemanticsProperties(
label: AppLocalizations.of(context)!.skipToPreviousTrackButtonTooltip,
button: true,
),
container: true,
Expand All @@ -51,8 +52,8 @@ class PlayerButtons extends StatelessWidget {
),
),
Semantics.fromProperties(
properties: const SemanticsProperties(
label: "Toggle playback",
properties: SemanticsProperties(
label: AppLocalizations.of(context)!.togglePlaybackButtonTooltip,
button: true,
),
container: true,
Expand Down Expand Up @@ -86,8 +87,8 @@ class PlayerButtons extends StatelessWidget {
),
),
Semantics.fromProperties(
properties: const SemanticsProperties(
label: "Skip to next track",
properties: SemanticsProperties(
label: AppLocalizations.of(context)!.skipToNextTrackButtonTooltip,
button: true,
),
container: true,
Expand Down
3 changes: 2 additions & 1 deletion lib/components/PlayerScreen/player_buttons_more.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_tabler_icons/flutter_tabler_icons.dart';
import 'package:get_it/get_it.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import '../../models/finamp_models.dart';

Expand All @@ -21,7 +22,7 @@ class PlayerButtonsMore extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return Semantics(
label: "Track menu",
label: AppLocalizations.of(context)!.trackMenuButtonTooltip,
excludeSemantics: true, // replace child semantics with custom semantics
container: true,
child: IconTheme(
Expand Down
27 changes: 10 additions & 17 deletions lib/components/PlayerScreen/player_buttons_repeating.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,16 @@ class PlayerButtonsRepeating extends StatelessWidget {
return StreamBuilder(
stream: mediaStateStream,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
return Semantics.fromProperties(
properties: SemanticsProperties(
label: "${getLocalizedLoopMode(context, queueService.loopMode)}. Tap to toggle.",
button: true,
),
excludeSemantics: true,
container: true,
child: IconButton(
onPressed: () async {
FeedbackHelper.feedback(FeedbackType.light);
queueService.toggleLoopMode();
},
icon: _getRepeatingIcon(
queueService.loopMode,
Theme.of(context).colorScheme.secondary,
)),
);
return IconButton(
tooltip: "${getLocalizedLoopMode(context, queueService.loopMode)}. ${AppLocalizations.of(context)!.genericToggleButtonTooltip}",
onPressed: () async {
FeedbackHelper.feedback(FeedbackType.light);
queueService.toggleLoopMode();
},
icon: _getRepeatingIcon(
queueService.loopMode,
Theme.of(context).colorScheme.secondary,
));
});
}

Expand Down
38 changes: 21 additions & 17 deletions lib/components/PlayerScreen/player_buttons_shuffle.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:flutter/rendering.dart';
import 'package:flutter_tabler_icons/flutter_tabler_icons.dart';
import 'package:flutter_vibrate/flutter_vibrate.dart';
import 'package:get_it/get_it.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

class PlayerButtonsShuffle extends StatelessWidget {
final audioHandler = GetIt.instance<MusicPlayerBackgroundTask>();
Expand All @@ -21,26 +22,29 @@ class PlayerButtonsShuffle extends StatelessWidget {
return StreamBuilder(
stream: mediaStateStream,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
return Semantics.fromProperties(
properties: SemanticsProperties(
label: "Playing ${_queueService.playbackOrder == FinampPlaybackOrder.shuffled ? "shuffled" : "in order"}. Tap to toggle.",
button: true,
),
excludeSemantics: true,
container: true,
child: IconButton(
onPressed: () async {
FeedbackHelper.feedback(FeedbackType.light);
_queueService.togglePlaybackOrder();
},
icon: Icon(
(_queueService.playbackOrder == FinampPlaybackOrder.shuffled
? TablerIcons.arrows_shuffle
: TablerIcons.arrows_right),
),
return IconButton(
tooltip: getLocalizedPlaybackOrder(context, _queueService.playbackOrder),
onPressed: () async {
FeedbackHelper.feedback(FeedbackType.light);
_queueService.togglePlaybackOrder();
},
icon: Icon(
(_queueService.playbackOrder == FinampPlaybackOrder.shuffled
? TablerIcons.arrows_shuffle
: TablerIcons.arrows_right),
),
);
},
);
}

String getLocalizedPlaybackOrder(BuildContext context, FinampPlaybackOrder playbackOrder) {
switch (playbackOrder) {
case FinampPlaybackOrder.linear:
return AppLocalizations.of(context)!.playbackOrderLinearButtonTooltip;
case FinampPlaybackOrder.shuffled:
return AppLocalizations.of(context)!.playbackOrderShuffledButtonTooltip;
}
}

}
3 changes: 2 additions & 1 deletion lib/components/PlayerScreen/player_screen_album_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_vibrate/flutter_vibrate.dart';
import 'package:get_it/get_it.dart';
import 'package:simple_gesture_detector/simple_gesture_detector.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import '../../services/current_album_image_provider.dart';
import '../../services/favorite_provider.dart';
Expand All @@ -35,7 +36,7 @@ class PlayerScreenAlbumImage extends ConsumerWidget {
final currentTrack = snapshot.data!.currentTrack;

return Semantics(
label: "Artwork for ${currentTrack?.item.title}. Tap to toggle playback. Swipe left or right to switch tracks.",
label: AppLocalizations.of(context)!.playerAlbumArtworkTooltip(currentTrack?.item.title ?? AppLocalizations.of(context)!.unknownName),
excludeSemantics: true, // replace child semantics with custom semantics
container: true,
child: GestureDetector(
Expand Down
5 changes: 4 additions & 1 deletion lib/components/PlayerScreen/progress_slider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:get_it/get_it.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import '../../services/music_player_background_task.dart';

Expand Down Expand Up @@ -235,7 +236,9 @@ class __PlaybackProgressSliderState
final durationFullHours = (widget.mediaItem?.duration?.inHours ?? 0);
final durationFullMinutes = (widget.mediaItem?.duration?.inMinutes ?? 0) % 60;
final durationSeconds = (widget.mediaItem?.duration?.inSeconds ?? 0) % 60;
return "${positionFullHours > 0 ? "$positionFullHours hours " : ""}${positionFullMinutes > 0 ? "$positionFullMinutes minutes " : ""}$positionSeconds seconds of ${durationFullHours > 0 ? "$durationFullHours hours " : ""}${durationFullMinutes > 0 ? "$durationFullMinutes minutes " : ""}$durationSeconds seconds";
final positionString = "${positionFullHours > 0 ? "$positionFullHours ${AppLocalizations.of(context)!.hours} " : ""}${positionFullMinutes > 0 ? "$positionFullMinutes ${AppLocalizations.of(context)!.minutes} " : ""}$positionSeconds ${AppLocalizations.of(context)!.seconds}";
final durationString = "${durationFullHours > 0 ? "$durationFullHours ${AppLocalizations.of(context)!.hours} " : ""}${durationFullMinutes > 0 ? "$durationFullMinutes ${AppLocalizations.of(context)!.minutes} " : ""}$durationSeconds ${AppLocalizations.of(context)!.seconds}";
return AppLocalizations.of(context)!.timeFractionTooltip(positionString, durationString);
},
secondaryTrackValue:
widget.mediaItem?.extras?["downloadedSongPath"] == null
Expand Down
3 changes: 2 additions & 1 deletion lib/components/PlayerScreen/song_name_content.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:finamp/screens/player_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter/semantics.dart';
import 'package:get_it/get_it.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import '../../services/queue_service.dart';
import 'album_chip.dart';
Expand Down Expand Up @@ -58,7 +59,7 @@ class SongNameContent extends StatelessWidget {
),
child: Semantics.fromProperties(
properties: SemanticsProperties(
label: "${currentTrack.item.title} (Title)",
label: "${currentTrack.item.title} (${AppLocalizations.of(context)!.title})",
),
excludeSemantics: true,
container: true,
Expand Down
4 changes: 3 additions & 1 deletion lib/components/album_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_blurhash/flutter_blurhash.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:octo_image/octo_image.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import '../models/jellyfin_models.dart';
import '../services/album_image_provider.dart';
Expand Down Expand Up @@ -75,7 +76,8 @@ class AlbumImage extends ConsumerWidget {
}

return Semantics(
label: "Artwork${item?.name != null ? "for ${item?.name}" : ""}",
// label: item?.name != null ? AppLocalizations.of(context)!.artworkTooltip(item!.name!) : AppLocalizations.of(context)!.artwork, // removed to reduce screen reader verbosity
excludeSemantics: true,
child: AspectRatio(
aspectRatio: 1.0,
child: Align(
Expand Down
Loading

0 comments on commit 6ecdb9d

Please sign in to comment.