add more info for claim-preview-tile aria label

This commit is contained in:
btzr-io 2021-07-15 18:12:11 -05:00
parent 7c8c43d3a7
commit 60c5d3bf67
5 changed files with 66 additions and 26 deletions

View file

@ -2054,5 +2054,7 @@
"Item removed from Watch Later": "Item removed from Watch Later",
"Skip Navigation": "Skip Navigation",
"In Favorites": "In Favorites",
"%title% by %channelTitle%, %mediaDuration%": "%title% by %channelTitle%, %mediaDuration%",
"%title% by %channelTitle%": "%title% by %channelTitle%",
"--end--": "--end--"
}

View file

@ -14,20 +14,28 @@ import { selectMutedChannels } from 'redux/selectors/blocked';
import { selectBlackListedOutpoints, selectFilteredOutpoints } from 'lbryinc';
import { selectShowMatureContent } from 'redux/selectors/settings';
import ClaimPreviewTile from './view';
import formatMediaDuration from 'util/formatMediaDuration';
const select = (state, props) => ({
claim: props.uri && makeSelectClaimForUri(props.uri)(state),
channel: props.uri && makeSelectChannelForClaimUri(props.uri)(state),
isResolvingUri: props.uri && makeSelectIsUriResolving(props.uri)(state),
thumbnail: props.uri && makeSelectThumbnailForUri(props.uri)(state),
title: props.uri && makeSelectTitleForUri(props.uri)(state),
blackListedOutpoints: selectBlackListedOutpoints(state),
filteredOutpoints: selectFilteredOutpoints(state),
blockedChannelUris: selectMutedChannels(state),
showMature: selectShowMatureContent(state),
isMature: makeSelectClaimIsNsfw(props.uri)(state),
isLivestream: makeSelectClaimIsStreamPlaceholder(props.uri)(state),
});
const select = (state, props) => {
const claim = props.uri && makeSelectClaimForUri(props.uri)(state);
const media = claim && claim.value && (claim.value.video || claim.value.audio);
const mediaDuration = media && media.duration && formatMediaDuration(media.duration, { screenReader: true });
return {
claim,
mediaDuration,
channel: props.uri && makeSelectChannelForClaimUri(props.uri)(state),
isResolvingUri: props.uri && makeSelectIsUriResolving(props.uri)(state),
thumbnail: props.uri && makeSelectThumbnailForUri(props.uri)(state),
title: props.uri && makeSelectTitleForUri(props.uri)(state),
blackListedOutpoints: selectBlackListedOutpoints(state),
filteredOutpoints: selectFilteredOutpoints(state),
blockedChannelUris: selectMutedChannels(state),
showMature: selectShowMatureContent(state),
isMature: makeSelectClaimIsNsfw(props.uri)(state),
isLivestream: makeSelectClaimIsStreamPlaceholder(props.uri)(state),
};
};
const perform = (dispatch) => ({
resolveUri: (uri) => dispatch(doResolveUri(uri)),

View file

@ -21,6 +21,7 @@ import CollectionPreviewOverlay from 'component/collectionPreviewOverlay';
type Props = {
uri: string,
claim: ?Claim,
mediaDuration?: string,
resolveUri: (string) => void,
isResolvingUri: boolean,
history: { push: (string) => void },
@ -72,6 +73,7 @@ function ClaimPreviewTile(props: Props) {
showNoSourceClaims,
isLivestream,
collectionId,
mediaDuration,
} = props;
const isRepost = claim && claim.repost_channel_url;
const isCollection = claim && claim.value_type === 'collection';
@ -114,6 +116,18 @@ function ClaimPreviewTile(props: Props) {
const signingChannel = claim && claim.signing_channel;
const channelUri = !isChannel ? signingChannel && signingChannel.permanent_url : claim && claim.permanent_url;
const channelTitle = signingChannel && (signingChannel.value.title || signingChannel.name);
// Aria-label value for claim preview
let ariaLabelData = title;
if (!isChannel && channelTitle) {
if (mediaDuration) {
ariaLabelData = __('%title% by %channelTitle%, %mediaDuration%', { title, channelTitle, mediaDuration });
} else {
ariaLabelData = __('%title% by %channelTitle%', { title, channelTitle });
}
}
function handleClick(e) {
if (navigateUrl) {
@ -226,7 +240,7 @@ function ClaimPreviewTile(props: Props) {
</FileThumbnail>
</NavLink>
<div className="claim-tile__header">
<NavLink {...navLinkProps}>
<NavLink aria-label={ariaLabelData} {...navLinkProps}>
<h2 className="claim-tile__title">
<TruncatedText text={title || (claim && claim.name)} lines={isChannel ? 1 : 2} />
{isChannel && (

View file

@ -1,6 +1,6 @@
// @flow
import React from 'react';
import formatMediaDuration from 'util/formatMediaDuration';
type Props = {
claim: ?StreamClaim,
className?: string,
@ -9,19 +9,11 @@ type Props = {
function VideoDuration(props: Props) {
const { claim, className } = props;
const video = claim && claim.value && (claim.value.video || claim.value.audio);
const media = claim && claim.value && (claim.value.video || claim.value.audio);
let duration;
if (video && video.duration) {
if (media && media.duration) {
// $FlowFixMe
let date = new Date(null);
date.setSeconds(video.duration);
let timeString = date.toISOString().substr(11, 8);
if (timeString.startsWith('00:')) {
timeString = timeString.substr(3);
}
duration = timeString;
duration = formatMediaDuration(media.duration);
}
return duration ? <span className={className}>{duration}</span> : null;

View file

@ -0,0 +1,24 @@
import moment from 'moment';
export default function formatMediaDuration(duration = 0, config) {
const options = {
screenReader: false,
...config,
};
// Optimize for screen readers
if (options.screenReader) {
return moment.utc(moment.duration(duration, 'seconds').asMilliseconds()).format('HH:mm:ss');
}
// Normal format
let date = new Date(null);
date.setSeconds(duration);
let timeString = date.toISOString().substr(11, 8);
if (timeString.startsWith('00:')) {
timeString = timeString.substr(3);
}
return timeString;
}